#ifndef INCLUDED_LOOP_
#define INCLUDED_LOOP_

#include <iosfwd>
#include <unordered_set>

#include "../globals/globals.h"
#include "../scenario/scenario.h"
#include "../screening/screening.h"
#include "../densities/densities.h"
#include "../modalities/modalities.h"
#include "../tumorinfo/tumorinfo.h"
#include "../tumor/tumor.h"
#include "../costs/costs.h"

class Scenario;

namespace FBB
{
    class CSVTable;
}

class Loop: public Globals
{
    enum Status
    {
        PRESENT,
        LEFT_PRE,           // left the pre, during, post screening
        LEFT_DURING,
        LEFT_POST,
        TUMOR_PRE,
        TUMOR_DURING,
        TUMOR_POST,
    };

    enum                    // round info (per case)
    {
        ATTENDED        = '1',
        FALSE_NEGATIVE  = '2',
        FALSE_POSITIVE  = '3'
    };
        
    enum
    {
        N_RESULTS = 13              // weird... used in results()
    };

    Status d_status = PRESENT;

    StringVect const &d_labels;

    Scenario d_scenario;
    Costs d_costs;
    Densities d_densities;
    TumorInfo d_tumorInfo;
    Tumor d_tumor;             
    Modalities d_modalities;
    Screening d_screening;

    bool d_selfDetected;
    uint16_t d_roundDetected;
        
            // Analysis &d_analysis;

            // Beir7 const &d_beir7;
            // Incidence const &d_incidence;

    double d_sumDeathAge = 0;
    double d_naturalDeathAge = 0;      // dying age w/o tumor
    double d_deathAge = 0;             // actual dying age

//FBBunused:
//    double d_detectionAge = 0;         // age at which the tumor is detected

    uint16_t d_nRounds;           
    uint16_t d_round = 0;               // currently used screening round

    std::string d_roundInfo;

    SizeVect d_nIntervals;
//    SizeVect d_nMam;                    // # rounds
//    SizeVect d_nTomo;
    SizeVect d_nRoundFP;                // # of false-positives per round
    SizeVect d_nRoundFN;                // # of false-negatives per round

//    SizeVect d_nModalityFP;             // # of false-positives per modality
                                        // -> Modalities
    SizeVect d_nDetections;

    double d_caseCost;
    double d_totalCost;

//  DoubleVect d_screeningCost;
    SizeVect d_roundCost;               // sum of costs over all scr. rounds
                                        // (org: screeningRoundCosts)

                                    // randomly determined bi-rad indices for
                                    // the ages of the screening rounds
    Uint16Vect d_biRadIndices;      // ('densities' in the original sources)
                                        
    std::string d_timestamp;

    static DoubleVect s_cumDeathProb;
    static std::unordered_set<std::string> s_availableFiles;

    //  sensitivity output file? loop.cpp line 40

    public:
        Loop(StringVect const &labels);

        void iterate();

    private:
        bool betaFunction(uint16_t modalityNr);

// ORG        void setBeir7dose();

        void genCases(size_t iter, size_t nCases);
        void caseInit();
        void resetCounters();

//        void checkSeed();           // reset the random generator unless
//                                    // using RANDOM_SEED

        void preScreen();
        void preTumorDeath();   // early natural death
        void selfDetected();    // self detected the tumor              // i.h

        void screening();                        
        bool leaving(double screeningAge); 
        void intervalCancer();                   

        void screen(double screeningAge);        
        void maybeDetect(ModBase *modBase, double screeningAge);
        void maybeFalsePositive(ModBase *modBase, double screeningAge);

        void postScreen();
        void treatmentDeath();                                          // .ih

        void characteristics(Status natural, Status tumor);

        size_t cases() const;                   // #cases in womenLoop

        double naturalDeathAge();

                // NOTE: in the orig. source density NRs are used: 1..4
                //       here density INDICES are usd: 0..3
                // but when writing the data file (e.g., data-0.txt, original
                // name e.g., women-test-i0.txt) a + 1 correction is 
                // currently applied
        bool use(ModBase *modBase);         // use this modality

                                        // add to totalCost, screeningCose
        void addCost(double cost);      //+ and womenCost
                                            
                                            // returns the sensitivity for the
        double sensitivity(ModBase *modBase) const;    // current round  1.cc

        void setStatus(Status status, double age);

        void labels(std::ostream &out) const;

        FBB::CSVTable headerData(size_t iter) const;
        FBB::CSVTable headerRounds(size_t iter) const;
        FBB::CSVTable headerSensitivity() const;  

        void writeParameters(size_t iter) const;    // also opens the file

        void writeSensitivity(FBB::CSVTable &sensTable, size_t iter) const; 
        void writeData(FBB::CSVTable &dataTable, size_t idx) const;
        void writeRounds(FBB::CSVTable &roundTable) const;

        static void fillZeroes(std::ostream &out, size_t idx);
        static std::ofstream outStream(std::string const &fname, size_t idx);
        static std::string replaceDollar(std::string const &settingsFile, 
                                         size_t idx);
        static std::ofstream open(std::string const &fname);

};
        
#endif

