#ifndef OPTS_H
#define OPTS_H

#include <vector>
#include <string>
#include <getopt.h>
#include <stdexcept>
#include <exception>

// Define a class to hold the options and parse arguments
class OptionParser
{
public:
    OptionParser() : verbose(false), printUsage(false) {}
    ~OptionParser() = default;

    void parseArguments(int argc, char *argv[], char **envp);
    std::string stringifyOptions(void) const;
    std::string getUsage() const;

    static OptionParser &getOptions(void)
    {
        static OptionParser options;
        return options;
    }

public:
    class Exception : public std::exception
    {
    public:
        Exception() = default;
        ~Exception() override = default;
        const char* what() const noexcept override = 0;
    };

    std::string argv0;
    std::vector<std::string> senseApiLibPath;
    std::vector<std::string> senseApiLibs;
    std::string dapSpecs;
    std::vector<std::string> dapSpecFiles;
    bool verbose, printUsage;

    static struct option longOptions[];
};

class OptionsParserError
: public std::invalid_argument, public OptionParser::Exception
{
public:
    OptionsParserError(
        const std::string& errorMessage, const OptionParser& parser);

    const char* what() const noexcept override;
};

class JustPrintUsageNoError
: public OptionParser::Exception
{
public:
    explicit JustPrintUsageNoError(const OptionParser& parser);
    const char* what() const noexcept override;

private:
    std::string message;
};

#endif // OPTS_H
