#ifndef INCLUDED_OPTIONS_
#define INCLUDED_OPTIONS_

#include <iostream>
#include <string>
#include <set>

#include "../flextypes/flextypes.h"

namespace FBB
{
    class Arg;
}

class Options: private FlexTypes
{
    enum PathType
    {
        FILENAME,
        PATHNAME
    };

    FBB::Arg const &d_arg;

    std::string const *d_matched = 0;   // text matched by the scanner,
    std::string const *d_rawString = 0; // initialized by the Parser
    std::string d_undelimit;            // used by textOf to remove the "
                                        // around a *d_matched string

        // The next four variables cannot have path-specifications with their
        // option/directive values. After their values have been obtained,
        // the setPathStrings member, called from Parser::cleanup, prefixes 
        // their values with the target directory's value
    std::string d_baseClassHeader;      // these options/directives cannot 
    std::string d_classHeader;          // have path names. See 
    std::string d_implementationHeader; // setPathStrings and assign/accept
    std::string d_lexSource;

    std::string d_baseClassSkeleton;
    std::string d_baseClassPreinclude;
    std::string d_className;
    std::string d_classSkeleton;
    std::string d_constructionPath;
    std::string d_filenames;
    std::string d_implementationSkeleton;
    std::string d_inputImplementation;
    std::string d_inputInlinePath;
    std::string d_inputInterfacePath;
    std::string d_lexFunctionName;
    std::string d_lexSkeleton;
    std::string d_nameSpace;
    std::string d_nameSpaceIdentifier;      // only alnum and _ characters
    std::string d_skeletonDirectory;
    std::string d_targetDirectory;
    std::string d_tokenPath;
    std::string d_infile;
    std::string d_startConditionName;

    bool d_interactive = false;
    bool d_lines;
    bool d_print = false;
    bool d_debug = false;
    bool d_matchedRules;
    bool d_verbose;
    bool d_caseSensitive;
    bool d_ownParser = false;

        // contains the names of used options/directives.  
        // Generator may warn if specified for already existing .h or .ih
        // files 
        // Warnings are issued for:
        //  class header:           class-name mismatch
        //                          namespace mismatch
        //                          not including the baseclass-header
        // implementation header:   not including the class header

    static std::set<std::string> s_warnOptions;    

    enum 
    {
        MAX_DEPTH = 10 
    };
    size_t d_maxDepth = MAX_DEPTH;

            // strings containing default file and other names
    static char s_defaultLexFunctionName[];
    static char s_defaultSkeletonDirectory[];
    static char s_defaultTokenPath[];
    static char s_defaultClassName[];
    static char s_defaultLexfunSource[];
    static char s_defaultStartConditionName[];

    static Options *s_options;
    static void (*s_regexCall)(char const *funName);

    public:
        static Options &instance();

        Options(Options const &other) = delete;

        void setParserInfo(std::string const &matched, 
                           std::string const &rawString);

        void setAccessorVariables();
        void showFilenames() const;
        void setPathStrings();

        bool caseSensitive() const;                                     // .f
        bool debug() const;                                             // .f
        bool interactive() const;                                       // .f
        bool lines() const;                                             // .f
        bool print() const;                                             // .f
        bool verbose() const;                                           // .f
        bool ownParserDebug() const;                                    // .f
        bool operator()(int opt) const;
        bool operator()(char const *opt) const;
        bool specified(std::string const &option) const;                // .f
        

        std::size_t maxDepth() const;                                   // .f

        std::string const &classHeaderPath() const;                     // .f
        std::string classHeaderName() const;

        std::string const &baseclassHeaderPath() const;                 // .f
        std::string baseclassHeaderName() const;

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

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

        std::string const &baseclassPreinclude() const;                 // .f
        std::string const &baseclassSkeleton() const;                   // .f
        std::string const &classSkeleton() const;                       // .f
        std::string const &className() const;                           // .f
        std::string const &filenames() const;                           // .f
        std::string const &implementationSkeleton() const;              // .f
        std::string const &inputImplementation() const;                 // .f
        std::string const &inputInline() const;                         // .f
        std::string const &inputInterface() const;                      // .f
        std::string const &lexFunctionName() const;                     // .f
        std::string const &lexSkeleton() const;                         // .f
        std::string const &nameSpace() const;                           // .f
        std::string const &nameSpaceIdentifier() const;                 // .f
        std::string const &infile() const;                              // .f
        std::string const &constructionPath() const;                    // .f
        std::string const &startConditionName() const;                  // .f
        std::string const &tokenPath() const;                           // .f

        std::string implementationHeaderName() const;

        void setBaseClassHeader(TextType textType);                     // .f
        void setBaseClassPreinclude(TextType textType);                 // .f
        void setClassHeader(TextType textType);                         // .f
        void setClassName(TextType textType);
        void setCaseInsensitive();                                      // .f
        void setDebug();                                                // .f
        void setFilenames(TextType textType);
        void setImplementationHeader(TextType textType);                // .f
        void setInputImplementationPath(TextType textType);             // .f
        void setInputInlinePath(TextType textType);                     // .f
        void setInputInterfacePath(TextType textType);                  // .f
        void setInteractive();                                          // .f
        void setLexFunctionName(TextType textType);
        void setLexSource(TextType textType);                           // .f
        void setLines(bool yesNo);                                      // .f
        void setNameSpace(TextType textType);                           // .f
        void setPrint();                                                // .f
        void setSkeletonDirectory(TextType textType);                   // .f
        void setStartConditionName(TextType newName);
        void setTargetDirectory(TextType textType);                     // .f
        void setTokenPath(TextType textType);                           // .f

        static void regexCall(char const *funname);                     // .f

        static char const *classHeaderSpec();   // long option/directive   .f
                                                // specs. used repeatedly
        static char const *baseclassHeaderSpec();                       // .f
        static char const *implementationHeaderSpec();                  // .f
        static char const *lexSourceSpec();                             // .f
        
    private:
        Options();  // FBB::Arg const &arg);

        std::string const &textOf(TextType type);

        void assign(TextType textType, std::string *target, PathType pathType, 
                    char const *declTxt);
        void accept(std::string const &text, 
                    PathType pathType, char const *declTxt);

        void setOptionPath(std::string *dest, int optChar, 
                           std::string const &defaultFile, 
                           char const *defaultSuffix,
                           char const *optionName);

        void setNameSpaceIdentifier();

        static void nop(char const *);                                  // .ih
        static void show(char const *funName);                          // .ih
};

#include "options.f"

#endif






