// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef SRC_TINT_UTILS_CLI_CLI_H_
#define SRC_TINT_UTILS_CLI_CLI_H_

#include <deque>
#include <optional>
#include <string>
#include <utility>

#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/memory/block_allocator.h"
#include "src/tint/utils/result/result.h"
#include "src/tint/utils/strconv/parse_num.h"
#include "src/tint/utils/text/string.h"

namespace tint::cli {

/// Alias is a fluent-constructor helper for Options
struct Alias {
    /// The alias to apply to an Option
    std::string value;

    /// @param option the option to apply the alias to
    template <typename T>
    void Apply(T& option) {
        option.alias = value;
    }
};

/// ShortName is a fluent-constructor helper for Options
struct ShortName {
    /// The short-name to apply to an Option
    std::string value;

    /// @param option the option to apply the short name to
    template <typename T>
    void Apply(T& option) {
        option.short_name = value;
    }
};

/// Parameter is a fluent-constructor helper for Options
struct Parameter {
    /// The parameter name to apply to an Option
    std::string value;

    /// @param option the option to apply the parameter name to
    template <typename T>
    void Apply(T& option) {
        option.parameter = value;
    }
};

/// Default is a fluent-constructor helper for Options
template <typename T>
struct Default {
    /// The default value to apply to an Option
    T value;

    /// @param option the option to apply the default value to
    template <typename O>
    void Apply(O& option) {
        option.default_value = value;
    }
};

/// Deduction guide for Default
template <typename T>
Default(T) -> Default<T>;

/// Option is the base class for all command line options
class Option {
  public:
    /// An alias to std::string, used to hold error messages.
    using Error = std::string;

    /// Constructor
    Option();

    /// Destructor
    virtual ~Option();

    /// @return the name of the option, without any leading hyphens.
    /// Example: 'help'
    virtual std::string Name() const = 0;

    /// @return the alias name of the option, without any leading hyphens. (optional)
    /// Example: 'flag'
    virtual std::string Alias() const = 0;

    /// @return the shorter name of the option, without any leading hyphens. (optional)
    /// Example: 'h'
    virtual std::string ShortName() const = 0;

    /// @return a string describing the parameter that the option expects.
    /// Empty represents no expected parameter.
    virtual std::string Parameter() const = 0;

    /// @return a description of the option.
    /// Example: 'shows this message'
    virtual std::string Description() const = 0;

    /// @return the default value of the option, or an empty string if there is no default value.
    virtual std::string DefaultValue() const = 0;

    /// Sets the option value to the default (called before arguments are parsed)
    virtual void SetDefault() = 0;

    /// Parses the option's arguments from the list of command line arguments, removing the consumed
    /// arguments before returning. @p arguments will have already had the option's name consumed
    /// before calling.
    /// @param arguments the queue of unprocessed arguments. Parse() may take from the front of @p
    /// arguments.
    /// @return empty Error if successfully parsed, otherwise an error string.
    virtual Error Parse(std::deque<std::string_view>& arguments) = 0;

  protected:
    /// An empty string, used to represent no-error.
    static constexpr const char* Success = "";

    /// @param expected the expected value(s) for the option
    /// @return an Error message for a missing argument
    Error ErrMissingArgument(std::string expected) const {
        Error err = "missing value for option '--" + Name() + "'";
        if (!expected.empty()) {
            err += "Expected: " + expected;
        }
        return err;
    }

    /// @param got the argument value provided
    /// @param reason the reason the argument is invalid (optional)
    /// @return an Error message for an invalid argument
    Error ErrInvalidArgument(std::string_view got, std::string reason) const {
        Error err = "invalid value '" + std::string(got) + "' for option '--" + Name() + "'";
        if (!reason.empty()) {
            err += "\n" + reason;
        }
        return err;
    }

  private:
    Option(const Option&) = delete;
    Option& operator=(const Option&) = delete;
    Option(Option&&) = delete;
    Option& operator=(Option&&) = delete;
};

/// Options for OptionSet::Parse
struct ParseOptions {
    /// If true, then unknown flags will be ignored instead of treated as an error
    bool ignore_unknown = false;
};

/// OptionSet is a set of Options, which can parse the command line arguments.
class OptionSet {
  public:
    /// Unconsumed is a list of unconsumed command line arguments
    using Unconsumed = Vector<std::string_view, 8>;

    /// Constructs and returns a new Option to be owned by the OptionSet
    /// @tparam T the Option type
    /// @tparam ARGS the constructor argument types
    /// @param args the constructor arguments
    /// @return the constructed Option
    template <typename T, typename... ARGS>
    T& Add(ARGS&&... args) {
        return *options.Create<T>(std::forward<ARGS>(args)...);
    }

    /// Prints to @p out the description of all the command line options.
    /// @param out the output stream
    void ShowHelp(std::ostream& out);

    /// Parses all the options in @p options.
    /// @param arguments the command line arguments, excluding the initial executable name
    /// @param parse_options the optional parser options
    /// @return a Result holding a list of arguments that were not consumed as options
    Result<Unconsumed> Parse(VectorRef<std::string_view> arguments,
                             const ParseOptions& parse_options = {});

  private:
    /// The list of options to parse
    BlockAllocator<Option, 1024> options;
};

/// ValueOption is an option that accepts a single value
template <typename T>
class ValueOption : public Option {
    static constexpr bool is_bool = std::is_same_v<T, bool>;
    static constexpr bool is_number =
        !is_bool && (std::is_integral_v<T> || std::is_floating_point_v<T>);
    static constexpr bool is_string = std::is_same_v<T, std::string>;
    static_assert(is_bool || is_number || is_string, "unsupported data type");

  public:
    /// The name of the option, without any leading hyphens.
    std::string name;
    /// The alias name of the option, without any leading hyphens.
    std::string alias;
    /// The shorter name of the option, without any leading hyphens.
    std::string short_name;
    /// A description of the option.
    std::string description;
    /// The default value.
    std::optional<T> default_value;
    /// The option value. Populated with Parse().
    std::optional<T> value;
    /// A string describing the name of the option's value.
    std::string parameter = "value";

    /// Constructor
    ValueOption() = default;

    /// Constructor
    /// @param option_name the option name
    /// @param option_description the option description
    /// @param settings a number of fluent-constructor values that configure the option
    /// @see ShortName, Parameter, Default
    template <typename... SETTINGS>
    ValueOption(std::string option_name, std::string option_description, SETTINGS&&... settings)
        : name(std::move(option_name)), description(std::move(option_description)) {
        (settings.Apply(*this), ...);
    }

    std::string Name() const override { return name; }

    std::string Alias() const override { return alias; }

    std::string ShortName() const override { return short_name; }

    std::string Parameter() const override { return parameter; }

    std::string Description() const override { return description; }

    std::string DefaultValue() const override {
        return default_value.has_value() ? ToString(*default_value) : "";
    }

    void SetDefault() override { value = default_value; }

    Error Parse(std::deque<std::string_view>& arguments) override {
        TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);

        if (arguments.empty()) {
            if constexpr (is_bool) {
                // Treat as flag (--blah)
                value = true;
                return Success;
            } else {
                return ErrMissingArgument(parameter);
            }
        }

        auto arg = arguments.front();

        if constexpr (is_number) {
            auto result = ParseNumber<T>(arg);
            if (result) {
                value = result.Get();
                arguments.pop_front();
                return Success;
            }
            if (result.Failure() == ParseNumberError::kResultOutOfRange) {
                return ErrInvalidArgument(arg, "value out of range");
            }
            return ErrInvalidArgument(arg, "failed to parse value");
        } else if constexpr (is_string) {
            value = arg;
            arguments.pop_front();
            return Success;
        } else if constexpr (is_bool) {
            if (arg == "true") {
                value = true;
                arguments.pop_front();
                return Success;
            }
            if (arg == "false") {
                value = false;
                arguments.pop_front();
                return Success;
            }
            // Next argument is assumed to be another option, or unconsumed argument.
            // Treat as flag (--blah)
            value = true;
            return Success;
        }

        TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
    }
};

/// BoolOption is an alias to ValueOption<bool>
using BoolOption = ValueOption<bool>;

/// StringOption is an alias to ValueOption<std::string>
using StringOption = ValueOption<std::string>;

/// EnumName is a pair of enum value and name.
/// @tparam ENUM the enum type
template <typename ENUM>
struct EnumName {
    /// Constructor
    EnumName() = default;

    /// Constructor
    /// @param v the enum value
    /// @param n the name of the enum value
    EnumName(ENUM v, std::string n) : value(v), name(std::move(n)) {}

    /// the enum value
    ENUM value;
    /// the name of the enum value
    std::string name;
};

/// Deduction guide for EnumName
template <typename ENUM>
EnumName(ENUM, std::string) -> EnumName<ENUM>;

/// EnumOption is an option that accepts an enumerator of values
template <typename ENUM>
class EnumOption : public Option {
  public:
    /// The name of the option, without any leading hyphens.
    std::string name;
    /// The alias name of the option, without any leading hyphens.
    std::string alias;
    /// The shorter name of the option, without any leading hyphens.
    std::string short_name;
    /// A description of the option.
    std::string description;
    /// The enum options as a pair of enum value to name
    Vector<EnumName<ENUM>, 8> enum_names;
    /// The default value.
    std::optional<ENUM> default_value;
    /// The option value. Populated with Parse().
    std::optional<ENUM> value;

    /// Constructor
    EnumOption() = default;

    /// Constructor
    /// @param option_name the option name
    /// @param option_description the option description
    /// @param names The enum options as a pair of enum value to name
    /// @param settings a number of fluent-constructor values that configure the option
    /// @see ShortName, Parameter, Default
    template <typename... SETTINGS>
    EnumOption(std::string option_name,
               std::string option_description,
               VectorRef<EnumName<ENUM>> names,
               SETTINGS&&... settings)
        : name(std::move(option_name)),
          description(std::move(option_description)),
          enum_names(std::move(names)) {
        (settings.Apply(*this), ...);
    }

    std::string Name() const override { return name; }

    std::string ShortName() const override { return short_name; }

    std::string Alias() const override { return alias; }

    std::string Parameter() const override { return PossibleValues("|"); }

    std::string Description() const override { return description; }

    std::string DefaultValue() const override {
        for (auto& enum_name : enum_names) {
            if (enum_name.value == default_value) {
                return enum_name.name;
            }
        }
        return "";
    }

    void SetDefault() override { value = default_value; }

    Error Parse(std::deque<std::string_view>& arguments) override {
        if (arguments.empty()) {
            return ErrMissingArgument("one of: " + PossibleValues(", "));
        }
        auto& arg = arguments.front();
        for (auto& enum_name : enum_names) {
            if (enum_name.name == arg) {
                value = enum_name.value;
                arguments.pop_front();
                return Success;
            }
        }
        return ErrInvalidArgument(arg, "Must be one of: " + PossibleValues(", "));
    }

    /// @param delimiter the delimiter between each enum option
    /// @returns the accepted enum names delimited with @p delimiter
    std::string PossibleValues(std::string delimiter) const {
        std::string out;
        for (auto& enum_name : enum_names) {
            if (!out.empty()) {
                out += delimiter;
            }
            out += enum_name.name;
        }
        return out;
    }
};

}  // namespace tint::cli

#endif  // SRC_TINT_UTILS_CLI_CLI_H_
