#ifndef INCLUDED_BASE_
#define INCLUDED_BASE_

#include <unordered_map>

#include "../usingdecl/usingdecl.h"

struct Base: public UsingDecl
{
    enum Action
    {
        NONE,           // initial value when no action option has been read
        COMPILE,
        DEPENDENCIES,
        EXECUTE,
        FORCED,
        MULTICOMP,
        PREPROCESS,
        SCRIPT,         // -t option 
        SOURCE,
        SPCH,
        UNASSEMBLE,

        ICMAKE,         // no action, but used by Options::arguments
    };

    enum ExecType
    {
        CHILD,
        DIRECT
    };

    private:
        static std::string s_tmpDir;

        static std::unordered_map<Action, char const *> s_actionName;

    public:
        Base() = default;

        static std::string useExt(std::string const &filename,
                                  char const *ext);

                                                    // throws
        static void invalid(Action action, char const *arg);
        static std::string const &tmpDir();                 // inline

        // show() and enter() are support members only used during 
        // icmake's construction process.

            // if msg[0] == 'X' then X is skipped and OptLong::nextIdx is
            // shown after 'msg'
            static void show(char const *msg, PtrVect const &ptrVect, 
                             bool throws = true);

            static void enter();                // throws after pressing enter

    protected:
        static char const *actionName(Action action);       // inline    
        static void setTmpDir(std::string &tmpDir);         // may add '/'

        static bool isDir(std::string const &path);
        static bool isWritable(std::string &dirName);   // true? -> ends in / 

        static std::string getHome();                   // ends in /

    private:
        static void checkTmpDir(std::string &tmpDir);   // may throw
        static std::string iniTmpDir();
};

// static
inline std::string const &Base::tmpDir()
{
    return s_tmpDir;
}

// static
inline char const *Base::actionName(Action action)
{
    return s_actionName.find(action)->second;
}

#endif
