#include <algorithm>
#include <array>
#include <list>
#include <cassert>
#include <string>
#include <set>

#include "argparse.hpp"
#include "argparse_util.hpp"

namespace argparse {


    /*
     * ArgumentParser
     */

    ArgumentParser::ArgumentParser(std::string prog_name, std::string description_str, std::ostream& os)
        : description_(description_str)
        , formatter_(new DefaultFormatter())
        , os_(os)
        {
        prog(prog_name);
        argument_groups_.push_back(ArgumentGroup("arguments"));
    }

    ArgumentParser& ArgumentParser::prog(std::string prog_name, bool basename_only) {
        if (basename_only) {
            prog_ = basename(prog_name);
        } else {
            prog_ = prog_name;
        }
        return *this;
    }

    ArgumentParser& ArgumentParser::version(std::string version_str) {
        version_ = version_str;
        return *this;
    }

    ArgumentParser& ArgumentParser::epilog(std::string epilog_str) {
        epilog_ = epilog_str;
        return *this;
    }

    ArgumentGroup& ArgumentParser::add_argument_group(std::string description_str) {
        argument_groups_.push_back(ArgumentGroup(description_str));
        return argument_groups_[argument_groups_.size() - 1];
    }

    void ArgumentParser::parse_args(int argc, const char* const* argv, int error_exit_code, int help_exit_code, int version_exit_code) {
        try {
            parse_args_throw(argc, argv);
        } catch (const argparse::ArgParseHelp&) {
            //Help requested
            print_help();
            std::exit(help_exit_code);
        } catch (const argparse::ArgParseVersion&) {
            print_version();
            std::exit(version_exit_code);
        } catch (const argparse::ArgParseError& e) {
            //Failed to parse
            std::cout << e.what() << "\n";

            std::cout << "\n";
            print_usage();
            std::exit(error_exit_code);
        }
    }

    void ArgumentParser::parse_args_throw(int argc, const char* const* argv) {
        std::vector<std::string> arg_strs;
        for (int i = 1; i < argc; ++i) {
            arg_strs.push_back(argv[i]);
        }

        parse_args_throw(arg_strs);
    }
    
    void ArgumentParser::parse_args_throw(std::vector<std::string> arg_strs) {
        add_help_option_if_unspecified();

        //Reset all the defaults
        for (const auto& group : argument_groups()) {
            for (const auto& arg : group.arguments()) {
                if (arg->default_set()) {
                    arg->set_dest_to_default();
                }
            }
        }

        //Create a look-up of expected argument strings and positional arguments
        std::map<std::string,std::shared_ptr<Argument>> str_to_option_arg;
        std::list<std::shared_ptr<Argument>> positional_args;
        for (const auto& group : argument_groups()) {
            for (const auto& arg : group.arguments()) {
                if (arg->positional()) {
                    positional_args.push_back(arg);
                } else {
                    for (const auto& opt : {arg->long_option(), arg->short_option()}) {
                        if (opt.empty()) continue;

                        auto ret = str_to_option_arg.insert(std::make_pair(opt, arg));

                        if (!ret.second) {
                            //Option string already specified
                            std::stringstream ss;
                            ss << "Option string '" << opt << "' maps to multiple options";
                            throw ArgParseError(ss.str());
                        }
                    }
                }
            }
        }

        std::set<std::shared_ptr<Argument>> specified_arguments;

        //Process the arguments
        for (size_t i = 0; i < arg_strs.size(); i++) {
            ShortArgInfo short_arg_info = no_space_short_arg(arg_strs[i], str_to_option_arg);

            std::shared_ptr<Argument> arg;

            if (short_arg_info.is_no_space_short_arg) {
                //Short argument with no space between value
                arg = short_arg_info.arg;
            } else { //Full argument
                auto iter = str_to_option_arg.find(arg_strs[i]);
                if (iter != str_to_option_arg.end()) {
                    arg = iter->second;
                }
            }

            if (arg) {
                //Start of an argument

                specified_arguments.insert(arg);

                if (arg->action() == Action::STORE_TRUE) {
                    arg->set_dest_to_true(); 
                } else if (arg->action() == Action::STORE_FALSE) {
                    arg->set_dest_to_false();
                } else if (arg->action() == Action::HELP) {
                    arg->set_dest_to_true(); 
                    throw ArgParseHelp();
                } else if (arg->action() == Action::VERSION) {
                    arg->set_dest_to_true(); 
                    throw ArgParseVersion();
                } else {
                    assert(arg->action() == Action::STORE);


                    size_t max_values_to_read = 0;
                    size_t min_values_to_read = 0;
                    if (arg->nargs() == '1') {
                        max_values_to_read = 1;
                        min_values_to_read = 1;
                    } else if (arg->nargs() == '?') {
                        max_values_to_read = 1;
                        min_values_to_read = 0;
                    } else if (arg->nargs() == '*') {
                        max_values_to_read = std::numeric_limits<size_t>::max();
                        min_values_to_read = 0;
                    } else {
                        assert (arg->nargs() == '+');
                        max_values_to_read = std::numeric_limits<size_t>::max();
                        min_values_to_read = 1;
                    }

                    std::vector<std::string> values;
                    size_t nargs_read = 0;
                    if (short_arg_info.is_no_space_short_arg) {
                        //It is a short argument, we already have the first value
                        if (!short_arg_info.value.empty()) {
                            values.push_back(short_arg_info.value);
                            ++nargs_read;
                        }
                    }
                    for (; nargs_read < max_values_to_read; ++nargs_read) {
                        size_t next_idx = i + 1 + nargs_read;
                        if (next_idx >= arg_strs.size()) {
                            std::stringstream msg;
                            msg << "Missing expected argument for " << arg_strs[i] << "";
                            throw ArgParseError(msg.str());

                        }
                        std::string str = arg_strs[next_idx];


                        if (is_argument(str, str_to_option_arg)) break;

                        values.push_back(str);
                    }

                    if (nargs_read < min_values_to_read) {
                        std::stringstream msg;
                        msg << "Expected at least " << min_values_to_read << " value(s) for argument '" << arg_strs[i] << "'";
                        throw ArgParseError(msg.str());
                    }
                    assert (nargs_read <= max_values_to_read);

                    //Set the option values appropriately
                    if (arg->nargs() == '1') {
                        assert(nargs_read == 1);
                        assert(values.size() == 1);

                        auto choices = arg->choices();
                        if (!choices.empty()) {
                            //Value must be one off the valid choices
                            auto find_iter = std::find(choices.begin(), choices.end(), values[0]);
                            if (find_iter == choices.end()) {
                                std::stringstream msg;
                                msg << "Unexpected option value '" << values[0] << "' (expected one of: " << join(choices, ", ");
                                msg << ") for " << arg->name();
                                throw ArgParseError(msg.str());
                            }
                        }


                        try {
                            arg->set_dest_to_value(values[0]); 
                        } catch (const ArgParseConversionError& e) {
                            std::stringstream msg;
                            msg << e.what() << " for " << arg->long_option();
                            auto short_opt = arg->short_option();
                            if (!short_opt.empty()) {
                                msg << "/" << short_opt;
                            }
                            throw ArgParseConversionError(msg.str());
                        }
                    } else {
                        //Multiple values
                        assert(false); //TODO: implement
                    }

                    if (!short_arg_info.is_no_space_short_arg) {
                        i += nargs_read; //Skip over the values (don't need to for short args)
                    }
                }

            } else {
                if (positional_args.empty()) {
                    //Unrecognized
                    std::stringstream ss;
                    ss << "Unexpected command-line argument '" << arg_strs[i] << "'";
                    throw ArgParseError(ss.str());
                } else {
                    //Positional argument
                    auto pos_arg = positional_args.front();
                    positional_args.pop_front();

                    try {
                        pos_arg->set_dest_to_value(arg_strs[i]); 
                    } catch (const ArgParseConversionError& e) {
                        std::stringstream msg;
                        msg << e.what() << " for positional argument " << pos_arg->long_option();
                        throw ArgParseConversionError(msg.str());
                    }

                    auto value = arg_strs[i];
                    specified_arguments.insert(pos_arg);
                }
            }
        }

        //Missing positionals?
        for(const auto& remaining_positional : positional_args) {
            std::stringstream ss;
            ss << "Missing required positional argument: " << remaining_positional->long_option();
            throw ArgParseError(ss.str());
        }

        //Missing required?
        for (const auto& group : argument_groups()) {
            for (const auto& arg : group.arguments()) {
                if (arg->required()) {
                    //potentially slow...
                    if (!specified_arguments.count(arg)) {
                        std::stringstream msg;
                        msg << "Missing required argument: " << arg->long_option();
                        auto short_opt = arg->short_option();
                        if (!short_opt.empty()) {
                            msg << "/" << short_opt;
                        }
                        throw ArgParseError(msg.str());
                    }
                }
            }
        }
    }

    void ArgumentParser::reset_destinations() {
        for (const auto& group : argument_groups()) {
            for (const auto& arg : group.arguments()) {
                arg->reset_dest();
            }
        }
    }

    void ArgumentParser::print_usage() {
        formatter_->set_parser(this);
        os_ << formatter_->format_usage();
    }

    void ArgumentParser::print_help() {
        formatter_->set_parser(this);
        os_ << formatter_->format_usage();
        os_ << formatter_->format_description();
        os_ << formatter_->format_arguments();
        os_ << formatter_->format_epilog();
    }

    void ArgumentParser::print_version() {
        formatter_->set_parser(this);
        os_ << formatter_->format_version();
    }

    std::string ArgumentParser::prog() const { return prog_; }
    std::string ArgumentParser::version() const { return version_; }
    std::string ArgumentParser::description() const { return description_; }
    std::string ArgumentParser::epilog() const { return epilog_; }
    std::vector<ArgumentGroup> ArgumentParser::argument_groups() const { return argument_groups_; }

    void ArgumentParser::add_help_option_if_unspecified() {
        //Has a help already been specified
        bool found_help = false;
        for(auto& grp : argument_groups_) {
            for(auto& arg : grp.arguments()) {
                if(arg->action() == Action::HELP) {
                    found_help = true;
                    break;
                }
            }
        }

        if (!found_help) {

            auto& grp = argument_groups_[0];

            grp.add_argument(show_help_dummy_, "--help", "-h")
                .help("Shows this help message")
                .action(Action::HELP);
        }
    }

    ArgumentParser::ShortArgInfo ArgumentParser::no_space_short_arg(std::string str, const std::map<std::string, std::shared_ptr<Argument>>& str_to_option_arg) const {

        ShortArgInfo short_arg_info;
        for(auto kv : str_to_option_arg) {
            if (kv.first.size() == 2) {
                //Is a short arg
                
                //String starts with short arg
                bool match = true;
                for (size_t i = 0; i < kv.first.size(); ++i) {
                    if (kv.first[i] != str[i]) {
                        match = false;
                        break;
                    }
                }

                bool no_space_between_short_arg_and_value = str.size() > kv.first.size();

                if (match && no_space_between_short_arg_and_value) {
                    //Only handles cases where there is no space between short arg and value
                    short_arg_info.is_no_space_short_arg = true;
                    short_arg_info.arg = kv.second;
                    short_arg_info.value = std::string(str.begin() + kv.first.size(), str.end());

                    return short_arg_info;
                }
            }
        }

        assert(!short_arg_info.is_no_space_short_arg);
        return short_arg_info;
    }

    /*
     * ArgumentGroup
     */
    ArgumentGroup::ArgumentGroup(std::string name_str)
        : name_(name_str)
        {}

    ArgumentGroup& ArgumentGroup::epilog(std::string str) {
        epilog_ = str;
        return *this;
    }
    std::string ArgumentGroup::name() const { return name_; }
    std::string ArgumentGroup::epilog() const { return epilog_; }
    const std::vector<std::shared_ptr<Argument>>& ArgumentGroup::arguments() const { return arguments_; }

    /*
     * Argument
     */
    Argument::Argument(std::string long_opt, std::string short_opt)
        : long_opt_(long_opt)
        , short_opt_(short_opt) {

        if (long_opt_.size() < 1) {
            throw ArgParseError("Argument must be at least one character long");
        }

        auto dashes_name = split_leading_dashes(long_opt_);

        if (dashes_name[0].size() == 1 && !short_opt_.empty()) {
            throw ArgParseError("Long option must be specified before short option");
        } else if (dashes_name[0].size() > 2) {
            throw ArgParseError("More than two dashes in argument name");
        }

        //Set defaults
        metavar_ = toupper(dashes_name[1]);
    }

    Argument& Argument::help(std::string help_str) {
        help_ = help_str;
        return *this;
    }

    Argument& Argument::nargs(char nargs_type) {
        //TODO: nargs > 1 support: '?', '*', '+'
        std::array<char,5> valid_nargs = {'0', '1'};

        auto iter = std::find(valid_nargs.begin(), valid_nargs.end(), nargs_type);
        if (iter == valid_nargs.end()) {
            throw ArgParseError("Invalid argument to nargs (must be one of: " + join(valid_nargs, ", ") + ")");
        }

        //Ensure nargs is consistent with the action
        if (action() == Action::STORE_FALSE && nargs_type != '0') {
            throw ArgParseError("STORE_FALSE action requires nargs to be '0'");
        } else if (action() == Action::STORE_TRUE && nargs_type != '0') {
            throw ArgParseError("STORE_TRUE action requires nargs to be '0'");
        } else if (action() == Action::HELP && nargs_type != '0') {
            throw ArgParseError("HELP action requires nargs to be '0'");
        } else if (action() == Action::STORE && nargs_type != '1') {
            throw ArgParseError("STORE action requires nargs to be '1'");
        }

        nargs_ = nargs_type;

        valid_action();
        return *this;
    }

    Argument& Argument::metavar(std::string metavar_str) {
        metavar_ = metavar_str;
        return *this;
    }

    Argument& Argument::choices(std::vector<std::string> choice_values) {
        choices_ = choice_values;
        return *this;
    }

    Argument& Argument::action(Action action_type) {
        action_ = action_type;

        if (   action_ == Action::STORE_FALSE 
            || action_ == Action::STORE_TRUE 
            || action_ == Action::HELP 
            || action_ == Action::VERSION) {
            this->nargs('0');
        } else if (action_ == Action::STORE) {
            this->nargs('1');
        } else {
            throw ArgParseError("Unrecognized argparse action");
        }

        return *this;
    }

    Argument& Argument::required(bool is_required) {
        required_ = is_required;
        return *this;
    }

    Argument& Argument::default_value(const std::string& value) {
        default_value_ = value;
        default_set_ = true;
        return *this;
    }

    Argument& Argument::group_name(std::string grp) {
        group_name_ = grp;
        return *this;
    }

    Argument& Argument::show_in(ShowIn show) {
        show_in_ = show;
        return *this;
    }

    std::string Argument::name() const { 
        std::string name_str = long_option();
        if (!short_option().empty()) {
            name_str += "/" + short_option();
        }
        return name_str;
    }

    std::string Argument::long_option() const { return long_opt_; }
    std::string Argument::short_option() const { return short_opt_; }
    std::string Argument::help() const { return help_; }
    char Argument::nargs() const { return nargs_; }
    std::string Argument::metavar() const { return metavar_; }
    std::vector<std::string> Argument::choices() const { return choices_; }
    Action Argument::action() const { return action_; }
    std::string Argument::default_value() const { return default_value_; }
    std::string Argument::group_name() const { return group_name_; }
    ShowIn Argument::show_in() const { return show_in_; }
    bool Argument::default_set() const { return default_set_; }

    bool Argument::required() const {
        if(positional()) {
            //Positional arguments are always required
            return true;
        }
        return required_;
    }
    bool Argument::positional() const {
        assert(long_option().size() > 1);
        return long_option()[0] != '-';
    }
} //namespace
