#ifndef INCLUDED_BOBCAT_ARGCONFIG_
#define INCLUDED_BOBCAT_ARGCONFIG_

#include <unordered_map>
#include <string>

#include <bobcat/arg>
#include <bobcat/configfile>

namespace FBB
{

class ArgConfig__;

class ArgConfig: public Arg, public ConfigFile
{
    static ArgConfig            *s_argconfig; // points to Singleton ArgConfig

    ArgConfig__ *d_ptr;

    public:
        static ArgConfig &initialize(char const *optstring,             // 1
            int argc, char **argv,
            Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        static ArgConfig &initialize(char const *optstring,             // 2
            int argc, char **argv, std::string const &fname,    
            Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        static ArgConfig &initialize(char const *optstring,             // 3
            LongOption const *const begin, LongOption const *const end,
            int argc, char **argv, Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        static ArgConfig &initialize(char const *optstring,             // 4
            LongOption const *const begin, LongOption const *const end,
            int argc, char **argv, std::string const &fname,
            Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        static ArgConfig &instance();        

        size_t option(int option);                                       // 1
        size_t option(std::string const &optchars);                      // 2
        size_t option(std::string *value, int optChar);                  // 3
        size_t option(std::string *value, char const *longOption);       // 4

        size_t option(size_t idx,                                   // 1.f
                        std::string *value, int option) const;      
        size_t option(size_t *idx,                                  // 2.f
                        std::string *value, int option) const;      
        size_t option(size_t idx, std::string *value,               // 3.f
                        char const *longOption) const;              
        size_t option(size_t *idx, std::string *value,              // 4.f
                      char const *longOption) const;                

        char const *operator[](size_t idx) const;   // Arg's []         .f
        std::string const &line(size_t idx) const;  // ConfigFile's []  .f

    private:
        ArgConfig(ArgConfig const &other) = delete;
        ArgConfig &operator=(ArgConfig const &other) = delete;

                                                                
        ArgConfig(char const *optstring,                        // 1
            int argc, char **argv,
            Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        ArgConfig(char const *optstring,                        // 2
            int argc, char **argv, std::string const &fname,    
            Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        ArgConfig(char const *optstring,                        // 3
            LongOption const *begin, LongOption const *const end,
            int argc, char **argv, Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        ArgConfig(char const *optstring,                        // 4
            LongOption const *begin, LongOption const *const end,
            int argc, char **argv, std::string const &fname,
            Comment cType = KeepComment, 
            SearchCasing sType = SearchCaseSensitive,
            Indices iType = IgnoreIndices);

        RE_iteratorPair findLongOption(int optChar);
        RE_iteratorPair longConfigOpt(std::string const &longOpt);
};

#include "option1.f"
#include "option2.f"
#include "option3.f"
#include "option4.f"
#include "opindex.f"
#include "line.f"

} // FBB

#endif

