#ifndef INCLUDED_TUMOR_
#define INCLUDED_TUMOR_

#include <cmath>

#include "../globals/globals.h"

class TumorInfo;
class Growth;
class Survival;

namespace FBB
{
    class CSVTable;
}

class Tumor: public Globals
{
    enum
    {                                       // max iterations when determining
        N_ITER_AGE = 15,                    // deathAge
    };

    static unsigned const N_YEARDAYS = 365;
    static constexpr double NO_TUMOR = -1;  

    TumorInfo const &d_tumorInfo;
    Growth const &d_growth;
    Survival const &d_survival;

    bool d_detected;        // tumor has been detected by screening
    bool d_interval;        // an interval cancer
    bool d_present;         // true: tumor is present

    double d_age;           // the age the tumor willl go clinical or NO_TUMOR
    double d_deathAge;      // death age because of the tumor
    double d_prePeriod;     // _preclin... #years before d_age

                                // the age where a tumor is potentially
                                // detectable on mammographic screening. 
                                // From this age onward it'll grow.
                                // (originally called _preclinAge)
    double d_detectableAge;     // (d_age - d_prePeriod)


    double d_pSurvival;     // p(Survival) after treatment
    double d_doublingDays;  // doubling time in days
    double d_doublingYears;  // doubling time in years

    double d_selfDetect;    // self-detect diameter (mm.)
    double d_startVolume;

    double d_volume;        // actual tumor volume
    double d_diameter;      // actual diameter (mm.)

    static constexpr double s_log2YearInv = 1 / (365 * log(2));
    static char const *s_noYes[];

    public:
        Tumor(TumorInfo const &tumorInfo);

        void reset();                       // reassign the modifiable members

        operator bool() const;              // true: tumor is active    .h
        double age() const;                 // self-detect age          .h
        double deathAge() const;                                    // .h
        double detectableAge() const;                               //  .h

        double volume() const;
        double diameter() const;

                                            // cpt the tumor's characteristics
        void characteristics(double age);   //+ at 'age'
        void characteristics();             // same, at d_age          .h

        void intervalCancer();                                      // .h
        void detected();                                            // .h

        void setDeathAge();                 // wrt d_age               .h
        void setDeathAge(double refAge);    // wrt reference age

        void writeData(FBB::CSVTable &tab) const;

    private:
        bool tumorAge();                    // false: no tumor
        void check(char const *type) const;
        uint16_t ageGroup() const;                                  // .ih

        double functionF(double years) const;
        double functionQ(double years) const;
        double functionZ(double years) const;

        static double volume(double diameter);
        static double diameter(double volume);

};

inline double Tumor::age() const
{
    return d_age;
}

inline double Tumor::detectableAge() const
{
    return d_detectableAge;
}

inline Tumor::operator bool() const
{
    return d_age != NO_TUMOR;
}

inline void Tumor::characteristics()
{
    characteristics(d_age);
}

inline void Tumor::intervalCancer()
{
    d_interval = true;
}

inline void Tumor::detected()
{
    d_detected = true;
}

inline void Tumor::setDeathAge()
{
    setDeathAge(d_age);
}

inline double Tumor::deathAge() const
{
    return d_deathAge;
}

inline double Tumor::diameter() const
{
    return d_diameter;
}

#endif
