#ifndef INCLUDED_TUMOR_
#define INCLUDED_TUMOR_

#include <iosfwd>
#include <cmath>

#include "../typedefs/typedefs.h"
#include "../globals/globals.h"
#include "../survival/survival.h"

class TumorInfo;
class Growth;

namespace FBB
{
    class CSVTable;
}

class Tumor: public Globals
{
    friend std::ostream &operator<<(std::ostream &out, Tumor const &tumor);

    enum
    {                                       // max iterations when determining
        N_ITER_AGE = 15,                    // deathAge
    };

    static unsigned const N_YEARDAYS = 365;
                                            // initialized tumor age at an
                                            // impossible age, so always
                                            // age < tumor age unless there
                                            // is a tumor (was: -1)
    static constexpr double NO_TUMOR = END_AGE + END_AGE;

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

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

    double d_selfDetectAge; // the age at which the tumor willl go clinical
                            // i.e., self-detected
                            // (selfDetectable(): true) or
                            // NO_TUMOR (selfDetectable(): false)

    double d_deathAge;      // death age because of the tumor
    double d_prePeriod;     // _preclin... #years before d_selfDetectAge

                                // the age where a tumor starts to grow and is
                                // potentially detectable on mammographic
                                // screening.  From this age onward it'll
                                // grow.  (originally called _preclinAge)
    double d_onset;         // (d_selfDetectAge - 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_startVolume;

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

    RowCol d_rowCol;

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

    public:
        Tumor(TumorInfo &tumorInfo);

        void reset();                       // reassign the modifiable members

        //operator bool() const; // true: tumor is active .f

        bool at(double age) const;      // true: tumor exists at 'age' .f

                                        // true: selfDetect <= 'age'   .f
        bool selfDetectBefore(double age) const; 

        double selfDetectAge() const;       // self-detect age          .f
        double deathAge() const;            // tumor-caused death age   .f
        double onset() const;                               //  .f

        double volume() const;
        double diameter() const;                                    // .f

        bool metastasis() const;            // only with lung cancer    .f

            // cpt the tumor's diameter and volume at 'age' if
            // d_onset <= age
        void   characteristicsAt(double age);                           // .cc

        void intervalCancer();                                      // .f

                                            // tumor found during
        void found();                       // the screening        // .f

        bool present() const;                                       // .f

        void setDeathAge();                 // wrt d_selfDetectAge  // .f
        void setDeathAge(double refAge);    // wrt reference age

        void checkDeath(double naturalDeathAge);
        void writeData(FBB::CSVTable &tab) const;

        RowCol const &rowCol() const;                               // .f

    private:
        std::ostream &insert(std::ostream &out) const;

        bool tumorAge();                    // false: no tumor
        void requireTumor(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);                      // .ih
        static double diameter(double volume);                      // .ih

        static double checkNot(double value);       // -1 at NO_TUMOR  .ih

};

// only used in reset: no needed as data member
//    double d_selfDetect;    // self-detect diameter (mm.)
//OBS:
//        bool selfDetectable() const;        // true: tumor selfDetectable .f


#include "tumor.f"
#endif
