// Copyright 2024 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.

#include "dawn/utils/CommandLineParser.h"

#include <algorithm>
#include <tuple>

#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"

namespace dawn::utils {

// OptionBase

CommandLineParser::OptionBase::OptionBase(std::string_view name, std::string_view desc)
    : mName(name), mDescription(desc), mParameter("value") {}

CommandLineParser::OptionBase::~OptionBase() = default;

const std::string& CommandLineParser::OptionBase::GetName() const {
    return mName;
}

std::string CommandLineParser::OptionBase::GetShortName() const {
    return mShortName;
}

const std::string& CommandLineParser::OptionBase::GetDescription() const {
    return mDescription;
}

std::string CommandLineParser::OptionBase::GetParameter() const {
    return mParameter;
}

bool CommandLineParser::OptionBase::IsSet() const {
    return mSet;
}

CommandLineParser::OptionBase::ParseResult CommandLineParser::OptionBase::Parse(
    absl::Span<const std::string_view> args) {
    auto result = ParseImpl(args);
    if (result.success) {
        mSet = true;
    }
    return result;
}

// BoolOption

CommandLineParser::BoolOption::BoolOption(std::string_view name, std::string_view desc)
    : Option(name, desc) {}

CommandLineParser::BoolOption::~BoolOption() = default;

bool CommandLineParser::BoolOption::GetValue() const {
    return mValue;
}

std::string CommandLineParser::BoolOption::GetParameter() const {
    return {};
}

CommandLineParser::OptionBase::ParseResult CommandLineParser::BoolOption::ParseImpl(
    absl::Span<const std::string_view> args) {
    // Explicit true
    if (!args.empty() && args.front() == "true") {
        if (IsSet()) {
            return {false, args, "cannot set multiple times with explicit true/false arguments"};
        }

        mValue = true;
        return {true, args.subspan(1)};
    }

    // Explicit false
    if (!args.empty() && args.front() == "false") {
        if (IsSet()) {
            return {false, args, "cannot set multiple times with explicit true/false arguments"};
        }

        mValue = false;
        return {true, args.subspan(1)};
    }

    // Assuming --option just means to set it to true. Allow setting the option multiple times
    // to true with this form.
    if (IsSet() && !mValue) {
        return {false, args, "cannot be set to both true and false"};
    }

    mValue = true;
    return {true, args};
}

// StringOption

CommandLineParser::StringOption::StringOption(std::string_view name, std::string_view desc)
    : Option(name, desc) {}

CommandLineParser::StringOption::~StringOption() = default;

std::string CommandLineParser::StringOption::GetValue() const {
    return mValue;
}

CommandLineParser::OptionBase::ParseResult CommandLineParser::StringOption::ParseImpl(
    absl::Span<const std::string_view> args) {
    if (IsSet()) {
        return {false, args, "cannot be set multiple times"};
    }

    if (args.empty()) {
        return {false, args, "expected a value"};
    }

    mValue = args.front();
    return {true, args.subspan(1)};
}

// StringListOption

CommandLineParser::StringListOption::StringListOption(std::string_view name, std::string_view desc)
    : Option(name, desc) {}

CommandLineParser::StringListOption::~StringListOption() = default;

absl::Span<const std::string> CommandLineParser::StringListOption::GetValue() const {
    return mValue;
}

std::vector<std::string> CommandLineParser::StringListOption::GetOwnedValue() const {
    std::vector<std::string> result;
    for (auto& v : mValue) {
        result.push_back(v);
    }
    return result;
}

CommandLineParser::OptionBase::ParseResult CommandLineParser::StringListOption::ParseImpl(
    absl::Span<const std::string_view> args) {
    if (args.empty()) {
        return {false, args, "expected a value"};
    }

    for (std::string_view s : absl::StrSplit(args.front(), ",")) {
        mValue.push_back(std::string{s});
    }
    return {true, args.subspan(1)};
}

// CommandLineParser

CommandLineParser::BoolOption& CommandLineParser::AddBool(std::string_view name,
                                                          std::string_view desc) {
    return AddOption(std::make_unique<BoolOption>(name, desc));
}

CommandLineParser::StringOption& CommandLineParser::AddString(std::string_view name,
                                                              std::string_view desc) {
    return AddOption(std::make_unique<StringOption>(name, desc));
}

CommandLineParser::StringListOption& CommandLineParser::AddStringList(std::string_view name,
                                                                      std::string_view desc) {
    return AddOption(std::make_unique<StringListOption>(name, desc));
}

// static
std::string CommandLineParser::JoinConversionNames(absl::Span<const std::string_view> names,
                                                   std::string_view separator) {
    return absl::StrJoin(names, separator);
}

CommandLineParser::BoolOption& CommandLineParser::AddHelp() {
    return AddBool("help", "Shows the help").ShortName('h');
}

// static
const CommandLineParser::ParseOptions CommandLineParser::kDefaultParseOptions = {};

CommandLineParser::ParseResult CommandLineParser::Parse(absl::Span<const std::string_view> args,
                                                        const ParseOptions& parseOptions) {
    // Build the map of name to option.
    absl::flat_hash_map<std::string, OptionBase*> nameToOption;

    for (auto& option : mOptions) {
        if (!nameToOption.emplace(option->GetName(), option.get()).second) {
            return {false,
                    absl::StrFormat("Duplicate options with name \"%s\"", option->GetName())};
        }

        if (!option->GetShortName().empty() &&
            !nameToOption.emplace(option->GetShortName(), option.get()).second) {
            return {false,
                    absl::StrFormat("Duplicate options with name \"%s\"", option->GetShortName())};
        }
    }

    auto nextArgs = args;
    while (!nextArgs.empty()) {
        auto arg = nextArgs.front();
        nextArgs = nextArgs.subspan(1);

        // Skip or error if it is not an option.
        if (arg.empty() || arg[0] != '-') {
            if (parseOptions.unknownIsError) {
                return {false, absl::StrFormat("Unknown option \"%s\"", arg)};
            }
            continue;
        }

        // Remove starting - or --
        arg = arg.substr(1);
        if (!arg.empty() && arg[0] == '-') {
            arg = arg.substr(1);
        }

        // Split at the = if there is one and use the right side as the option's arguments
        if (auto equalPos = arg.find('='); equalPos != std::string::npos) {
            auto name = arg.substr(0, equalPos);
            auto rest = arg.substr(equalPos + 1);

            // Skip or error if it is an unknown option.
            if (!nameToOption.contains(name)) {
                if (parseOptions.unknownIsError) {
                    return {false, absl::StrFormat("Unknown option \"%s\"", name)};
                }
                continue;
            }

            auto option = nameToOption[name];
            auto optionResult = option->Parse({&rest, 1});
            if (!optionResult.success) {
                return {false, absl::StrFormat("Failure while parsing \"%s\": %s",
                                               option->GetName(), optionResult.errorMessage)};
            }
            if (!optionResult.remainingArgs.empty()) {
                return {false, absl::StrFormat("Argument \"%s\" was not valid for option \"%s\"",
                                               rest, option->GetName())};
            }
            continue;
        }

        // Otherwise make the option greedily parse from the rest of the command line.
        // Skip or error if it is an unknown option.
        if (!nameToOption.contains(arg)) {
            if (parseOptions.unknownIsError) {
                return {false, absl::StrFormat("Unknown option \"%s\"", arg)};
            }
            continue;
        }

        // Try to parse the arg.
        auto option = nameToOption[arg];
        auto optionResult = option->Parse(nextArgs);
        if (!optionResult.success) {
            return {false, absl::StrFormat("Failure while parsing \"%s\": %s", option->GetName(),
                                           optionResult.errorMessage)};
        }
        nextArgs = optionResult.remainingArgs;
    }

    return {true};
}

CommandLineParser::ParseResult CommandLineParser::Parse(const std::vector<std::string>& args,
                                                        const ParseOptions& parseOptions) {
    std::vector<std::string_view> viewArgs;
    for (const auto& arg : args) {
        viewArgs.push_back(arg);
    }

    return Parse(viewArgs, parseOptions);
}

CommandLineParser::ParseResult CommandLineParser::Parse(int argc,
                                                        const char** argv,
                                                        const ParseOptions& parseOptions) {
    std::vector<std::string_view> args;
    for (int i = 1; i < argc; i++) {
        args.push_back(argv[i]);
    }

    return Parse(args, parseOptions);
}

void CommandLineParser::PrintHelp(std::ostream& s) {
    // Sort options in alphabetical order using a trick that std::tuple is sorted lexicographically.
    std::vector<std::tuple<std::string_view, OptionBase*>> sortedOptions;
    for (auto& option : mOptions) {
        sortedOptions.emplace_back(option->GetName(), option.get());
    }
    std::sort(sortedOptions.begin(), sortedOptions.end());

    for (auto& [name, option] : sortedOptions) {
        s << "--" << name;

        std::string parameter = option->GetParameter();
        if (!parameter.empty()) {
            s << " <" << parameter << ">";
        }

        const auto& desc = option->GetDescription();
        if (!desc.empty()) {
            s << "  " << desc;
        }

        s << "\n";

        if (!option->GetShortName().empty()) {
            s << "-" << option->GetShortName() << "  alias for --" << name << "\n";
        }
    }
}

}  // namespace dawn::utils
