#include <myapp/cmdargs/options.h>
#include <myapp/cmdargs/errors.h>
#include <experimental/filesystem>
#include <sstream>
#include <getopt.h>

namespace myapp::cmdargs {

static std::string optopt_string()
{
    return std::string(1, char(optopt));
}

static std::string optarg_path_config()
{
    namespace fs = std::experimental::filesystem;
    auto path = fs::u8path(optarg);
    auto path_str = path.string();

    if (!fs::exists(path))
        throw reading_file("config file can not be read '" + path_str + "'");

    return std::move(path_str);
}

options options::parse_arguments(int argc, char * const argv[])
{
    opterr = 0;
    optind = 1;

    options opt;

    int c;
    while ((c = getopt(argc, argv, ":hfC:r")) != -1)
    {
        switch (c)
        {
        case 'h':
            opt.showhelp = true;
            break;

        case 'f':
            opt.nofork = true;
            break;

        case 'r':
            opt.rcon = true;
            break;

        case 'C':
            opt.config = optarg_path_config();
            break;

        case ':':
            throw invalid_option_value("option requires an argument '-" + optopt_string() + "'");

        default: /* '?' */
            throw unknown_option("unrecognized option '-" + optopt_string() + "'");
        }
    }

    return opt;
}

std::string options::list_all()
{
    std::stringstream ss;
    ss << "Allowed options:" << std::endl
       << "  -h\tHelp (list all command line options)" << std::endl
       << "  -f\tStay in foreground mode" << std::endl
       << "  -r\tAttempt to connect to a running process and provide a console interface for controlling it" << std::endl
       << "  -C\tUse file as master configuration file instead of the default" << std::endl
       ;
    return ss.str();
}


} /* namespace myapp::cmdargs */
