#ifndef INCLUDED_OPTIONS_
#define INCLUDED_OPTIONS_

#include "../base/base.h"

struct option;                      // defined by getopt_long
class OptBase;

// See ./script.cc for a description of how the -t option is handled

class Options: public Base
{
    using ActionFun = bool (Options::*)();      // about(), etc.

                                    // options1.cc: specified/modified 
    PtrVect d_argv;                 // points to the chars of d_args

    std::string d_scriptBim;

    Action d_action;
                                    // cast by derived classes to their types
    OptBase *d_optBase;             // destroyed by Options at main's end

                                    // data.cc elements:
    static option s_actionLongOpts[];
    static char const *s_actionOptChars;
    static std::unordered_map<int, ActionFun> s_action;
    static std::string s_returnOpts;
    
    public:
        Options(unsigned argc, char **argv);                        // 1.cc
        ~Options();

        Action action() const;
        OptBase &optBase() const;

        static void usage(char const *argv0);                       // 1

    private:
        Options(char **argv, unsigned argc);                        // 2.cc

        bool about();               // called at -a
        bool compile();             // called at -c
        bool dependencies();        // called at -d
        bool execute();             // called at -e
        bool forced();              // called at -f
        bool multicomp();           // called at -m
        bool setNoProcess();        // called at -N
        bool setNoVersionCheck();   // called at -n
        bool preProcess();          // called at -p
        bool script();              // called at -t
        bool setTmpDir();           // called at -T
        bool setVerbose();          // called at -V
        bool source();              // called at -s
        bool spch();                // called at -S
        bool unassemble();          // called at -u
        bool usage();               // called at -h                 // 2
        bool version();             // called at -v

        void checkAction(Action action);

        void arguments();                   // calls:

                                            // -> dependencies.cc, execute.cc,
                                            //    multicomp.cc, spch.cc
        bool directOpts(Action action);     //    unassemble.cc
        bool sourceOpts(Action action);     // -> source.cc, script.cc
        bool compOpts(Action action,        // -> forced.cc, compile.cc
                      char const *options); //    preprocess.cc
        void separateActionOpts();          // calls:
        void split(size_t idx, size_t pos);
        static bool next(size_t *pos, std::string const &arg);
};

inline Options::Action Options::action() const
{
    return d_action;
}

inline OptBase &Options::optBase() const
{
    return *d_optBase;
}

#endif
