#ifndef INCLUDED_OPTIONS_
#define INCLUDED_OPTIONS_

#include <iosfwd>
#include <string>
#include <unordered_map>

#include "../enums/enums.h"

namespace FBB
{
    class Arg;
}

class Options
{
    enum Specified
    {
        STARTUP,
        ANALYSIS
    };

    FBB::Arg const &d_arg;

    std::string d_cumDeath;         // file containing the cum. death props.

    std::string d_home;             // current 'HOME' directory


    std::string d_specified[2];     // specified options:
                                    // [0]: command-line, [1]: analysis

    bool d_specificAges = false;
    double d_naturalDeathAge;       // single run, subject age
    double d_tumorAge;              // single run, tumor self-detect age


    size_t d_lastCase;              // compute until d_lastCase, report
                                    // d_lastCase's results


    std::string d_base[2];          // guaranteed to end in '/'
                                    // [0]: as specified, [1]: as used
                                    // in Analysis: sections

    std::string d_cancer[2];        // [0]: as specified, [1]: as used
                                    // in Analysis: sections

    std::string d_config[2];        // [0]: as specified, [1]: as used
                                    // in Analysis: sections

    std::string d_dataFile[2];      // [0]: as specified, [1]: as used
                                    // after replacing + by base
    std::string d_parametersFile[2];
    std::string d_roundsFile[2];
    std::string d_sensitivityFile[2];

    std::string d_spreadFile[2];

    static char const s_base[];
    static char const s_config[];
    static std::unordered_map<int, char const *> s_fileName;

    static Options *s_options;

    public:
        static Options &instance();

        Options(Options const &other) = delete;

        void reset();                           // reset options to the
                                                // default/command-line values

        std::string const &base() const;                // .f
        std::string const &configFile() const;          // .f
        std::string const &cumDeathFile() const;        // .f

        std::string const &parametersFile() const;              // .f
        std::string const &dataFile() const;                    // .f
        std::string const &roundsFile() const;                  // .f
        std::string const &sensitivityFile() const;             // .f

        std::string const &spreadFile() const;                  // .f

        bool specificAges() const;                              // .f

        void fixedNaturalDeathAge(double &deathAge) const;
        void fixedTumorAge(double &tumorAge) const;
        size_t lastCase() const;                                // .f


        void activate();                        // [ANALYSIS] = [STARTUP]

                                                // try to change this option's
                                                // value in this analysis
        bool alter(int optChar, std::string const &value);

        void actualize();                       // transform ~ and +

        bool tnm() const;                       // --tnm was specified

    private:
        Options();

        void baseOption();
        void configOption();
        void cumDeathOption(std::string const &value);

        void conflictCheck() const;         // prevent conflicting options

        void deathAge(std::string const &value);
        void deathAgeOption(std::string const &value);

        void fileOption(std::string *dest, int option);

        void lastCase(std::string const &value);
        void lastCaseOption(std::string const &value);

        void logOption(std::string const &value);

            // xxx[STARTUP]: as specified, xxx[ANALYSIS]: as used
        void replaceHome(std::string &path);
        void replacePlus(std::string &fname);

        void setBase();

        void setSimulationType();                   // handle the -c option

        void tumorAge(std::string const &value);
        void tumorAgeOption(std::string const &value);

            // dest[0]: as specified, dest[1]: as used
//        void setFile(std::string *dest, std::string const &newValue,    // 2
//                                        int option);

};

#include "options.f"

#endif
