/*
 * Copyright (c) 2017-2020, 2022 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifndef ARM_COMPUTE_UTILS_COMMANDLINEPARSER
#define ARM_COMPUTE_UTILS_COMMANDLINEPARSER

#include "Option.h"
#include "arm_compute/core/utils/misc/Utility.h"

#include <cstring>
#include <iostream>
#include <map>
#include <memory>
#include <memory>
#include <regex>
#include <string>
#include <utility>
#include <vector>

namespace arm_compute
{
namespace utils
{
/** Class to parse command line arguments. */
class CommandLineParser final
{
public:
    /** Default constructor. */
    CommandLineParser() = default;

    /** Function to add a new option to the parser.
     *
     * @param[in] name Name of the option. Will be available under --name=VALUE.
     * @param[in] args Option specific configuration arguments.
     *
     * @return Pointer to the option. The option is owned by the parser.
     */
    template <typename T, typename... As>
    T *add_option(const std::string &name, As &&... args);

    /** Function to add a new positional argument to the parser.
     *
     * @param[in] args Option specific configuration arguments.
     *
     * @return Pointer to the option. The option is owned by the parser.
     */
    template <typename T, typename... As>
    T *add_positional_option(As &&... args);

    /** Parses the command line arguments and updates the options accordingly.
     *
     * @param[in] argc Number of arguments.
     * @param[in] argv Arguments.
     */
    void parse(int argc, char **argv);

    /** Validates the previously parsed command line arguments.
     *
     * Validation fails if not all required options are provided. Additionally
     * warnings are generated for options that have illegal values or unknown
     * options.
     *
     * @return True if all required options have been provided.
     */
    bool validate() const;

    /** Prints a help message for all configured options.
     *
     * @param[in] program_name Name of the program to be used in the help message.
     */
    void print_help(const std::string &program_name) const;

private:
    using OptionsMap              = std::map<std::string, std::unique_ptr<Option>>;
    using PositionalOptionsVector = std::vector<std::unique_ptr<Option>>;

    OptionsMap               _options{};
    PositionalOptionsVector  _positional_options{};
    std::vector<std::string> _unknown_options{};
    std::vector<std::string> _invalid_options{};
};

template <typename T, typename... As>
inline T *CommandLineParser::add_option(const std::string &name, As &&... args)
{
    auto result = _options.emplace(name, std::make_unique<T>(name, std::forward<As>(args)...));
    return static_cast<T *>(result.first->second.get());
}

template <typename T, typename... As>
inline T *CommandLineParser::add_positional_option(As &&... args)
{
    _positional_options.emplace_back(std::make_unique<T>(std::forward<As>(args)...));
    return static_cast<T *>(_positional_options.back().get());
}

inline void CommandLineParser::parse(int argc, char **argv)
{
    const std::regex option_regex{ "--((?:no-)?)([^=]+)(?:=(.*))?" };

    const auto set_option = [&](const std::string & option, const std::string & name, const std::string & value)
    {
        if(_options.find(name) == _options.end())
        {
            _unknown_options.push_back(option);
            return;
        }

        const bool success = _options[name]->parse(value);

        if(!success)
        {
            _invalid_options.push_back(option);
        }
    };

    unsigned int positional_index = 0;

    for(int i = 1; i < argc; ++i)
    {
        std::string mixed_case_opt{ argv[i] };
        int         equal_sign = mixed_case_opt.find('=');
        int         pos        = (equal_sign == -1) ? strlen(argv[i]) : equal_sign;

        const std::string option = arm_compute::utility::tolower(mixed_case_opt.substr(0, pos)) + mixed_case_opt.substr(pos);
        std::smatch       option_matches;

        if(std::regex_match(option, option_matches, option_regex))
        {
            // Boolean option
            if(option_matches.str(3).empty())
            {
                set_option(option, option_matches.str(2), option_matches.str(1).empty() ? "true" : "false");
            }
            else
            {
                // Can't have "no-" and a value
                if(!option_matches.str(1).empty())
                {
                    _invalid_options.emplace_back(option);
                }
                else
                {
                    set_option(option, option_matches.str(2), option_matches.str(3));
                }
            }
        }
        else
        {
            if(positional_index >= _positional_options.size())
            {
                _invalid_options.push_back(mixed_case_opt);
            }
            else
            {
                _positional_options[positional_index]->parse(mixed_case_opt);
                ++positional_index;
            }
        }
    }
}

inline bool CommandLineParser::validate() const
{
    bool is_valid = true;

    for(const auto &option : _options)
    {
        if(option.second->is_required() && !option.second->is_set())
        {
            is_valid = false;
            std::cerr << "ERROR: Option '" << option.second->name() << "' is required but not given!\n";
        }
    }

    for(const auto &option : _positional_options)
    {
        if(option->is_required() && !option->is_set())
        {
            is_valid = false;
            std::cerr << "ERROR: Option '" << option->name() << "' is required but not given!\n";
        }
    }

    for(const auto &option : _unknown_options)
    {
        std::cerr << "WARNING: Skipping unknown option '" << option << "'!\n";
    }

    for(const auto &option : _invalid_options)
    {
        std::cerr << "WARNING: Skipping invalid option '" << option << "'!\n";
    }

    return is_valid;
}

inline void CommandLineParser::print_help(const std::string &program_name) const
{
    std::cout << "usage: " << program_name << " \n";

    for(const auto &option : _options)
    {
        std::cout << option.second->help() << "\n";
    }

    for(const auto &option : _positional_options)
    {
        std::string help_to_print;

        // Extract help sub-string
        const std::string help_str = option->help();
        const size_t      help_pos = help_str.find(" - ");
        if(help_pos != std::string::npos)
        {
            help_to_print = help_str.substr(help_pos);
        }

        std::cout << option->name() << help_to_print << "\n";
    }
}
} // namespace utils
} // namespace arm_compute
#endif /* ARM_COMPUTE_UTILS_COMMANDLINEPARSER */
