/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#pragma once

#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

template <typename FunctionSignature>
struct cmCommandLineArgument
{
  enum class Values
  {
    Zero,
    One,
    Two,
    ZeroOrOne,
    OneOrMore
  };

  enum class RequiresSeparator
  {
    Yes,
    No
  };

  enum class ParseMode
  {
    Valid,
    Invalid,
    SyntaxError,
    ValueError
  };

  std::string InvalidSyntaxMessage;
  std::string InvalidValueMessage;
  std::string Name;
  Values Type;
  RequiresSeparator SeparatorNeeded;
  std::function<FunctionSignature> StoreCall;

  template <typename FunctionType>
  cmCommandLineArgument(std::string n, Values t, FunctionType&& func)
    : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
    , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
    , Name(std::move(n))
    , Type(t)
    , SeparatorNeeded(RequiresSeparator::Yes)
    , StoreCall(std::forward<FunctionType>(func))
  {
  }

  template <typename FunctionType>
  cmCommandLineArgument(std::string n, Values t, RequiresSeparator s,
                        FunctionType&& func)
    : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
    , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
    , Name(std::move(n))
    , Type(t)
    , SeparatorNeeded(s)
    , StoreCall(std::forward<FunctionType>(func))
  {
  }

  template <typename FunctionType>
  cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
                        FunctionType&& func)
    : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
    , InvalidValueMessage(std::move(failedMsg))
    , Name(std::move(n))
    , Type(t)
    , SeparatorNeeded(RequiresSeparator::Yes)
    , StoreCall(std::forward<FunctionType>(func))
  {
  }

  template <typename FunctionType>
  cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
                        RequiresSeparator s, FunctionType&& func)
    : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
    , InvalidValueMessage(std::move(failedMsg))
    , Name(std::move(n))
    , Type(t)
    , SeparatorNeeded(s)
    , StoreCall(std::forward<FunctionType>(func))
  {
  }

  bool matches(std::string const& input) const
  {
    bool matched = false;
    if (this->Type == Values::Zero) {
      matched = (input == this->Name);
    } else if (this->SeparatorNeeded == RequiresSeparator::No) {
      matched = cmHasPrefix(input, this->Name);
    } else if (cmHasPrefix(input, this->Name)) {
      if (input.size() == this->Name.size()) {
        matched = true;
      } else {
        matched =
          (input[this->Name.size()] == '=' || input[this->Name.size()] == ' ');
      }
    }
    return matched;
  }

  template <typename T, typename... CallState>
  bool parse(std::string const& input, T& index,
             std::vector<std::string> const& allArgs,
             CallState&&... state) const
  {
    ParseMode parseState = ParseMode::Valid;

    if (this->Type == Values::Zero) {
      if (input.size() == this->Name.size()) {
        parseState =
          this->StoreCall(std::string{}, std::forward<CallState>(state)...)
          ? ParseMode::Valid
          : ParseMode::Invalid;
      } else {
        parseState = ParseMode::SyntaxError;
      }

    } else if (this->Type == Values::One || this->Type == Values::ZeroOrOne) {
      if (input.size() == this->Name.size()) {
        auto nextValueIndex = index + 1;
        if (nextValueIndex >= allArgs.size() ||
            allArgs[nextValueIndex][0] == '-') {
          if (this->Type == Values::ZeroOrOne) {
            parseState =
              this->StoreCall(std::string{}, std::forward<CallState>(state)...)
              ? ParseMode::Valid
              : ParseMode::Invalid;
          } else {
            parseState = ParseMode::ValueError;
          }
        } else {
          parseState = this->StoreCall(allArgs[nextValueIndex],
                                       std::forward<CallState>(state)...)
            ? ParseMode::Valid
            : ParseMode::Invalid;
          index = nextValueIndex;
        }
      } else {
        auto value = this->extract_single_value(input, parseState);
        if (parseState == ParseMode::Valid) {
          parseState =
            this->StoreCall(value, std::forward<CallState>(state)...)
            ? ParseMode::Valid
            : ParseMode::Invalid;
        }
      }
    } else if (this->Type == Values::Two) {
      if (input.size() == this->Name.size()) {
        if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' ||
            allArgs[index + 2][0] == '-') {
          parseState = ParseMode::ValueError;
        } else {
          index += 2;
          parseState =
            this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]),
                            std::forward<CallState>(state)...)
            ? ParseMode::Valid
            : ParseMode::Invalid;
        }
      }
    } else if (this->Type == Values::OneOrMore) {
      if (input.size() == this->Name.size()) {
        auto nextValueIndex = index + 1;
        if (nextValueIndex >= allArgs.size() ||
            allArgs[nextValueIndex][0] == '-') {
          parseState = ParseMode::ValueError;
        } else {
          std::string buffer = allArgs[nextValueIndex++];
          while (nextValueIndex < allArgs.size() &&
                 allArgs[nextValueIndex][0] != '-') {
            buffer = cmStrCat(buffer, ";", allArgs[nextValueIndex++]);
          }
          parseState =
            this->StoreCall(buffer, std::forward<CallState>(state)...)
            ? ParseMode::Valid
            : ParseMode::Invalid;
          index = (nextValueIndex - 1);
        }
      } else {
        auto value = this->extract_single_value(input, parseState);
        if (parseState == ParseMode::Valid) {
          parseState =
            this->StoreCall(value, std::forward<CallState>(state)...)
            ? ParseMode::Valid
            : ParseMode::Invalid;
        }
      }
    }

    if (parseState == ParseMode::SyntaxError) {
      cmSystemTools::Error(
        cmStrCat("'", input, "'", this->InvalidSyntaxMessage));
    } else if (parseState == ParseMode::ValueError) {
      cmSystemTools::Error(this->InvalidValueMessage);
    }
    return (parseState == ParseMode::Valid);
  }

private:
  std::string extract_single_value(std::string const& input,
                                   ParseMode& parseState) const
  {
    // parse the string to get the value
    auto possible_value = cm::string_view(input).substr(this->Name.size());
    if (possible_value.empty()) {
      parseState = ParseMode::ValueError;
    } else if (possible_value[0] == '=') {
      possible_value.remove_prefix(1);
      if (possible_value.empty()) {
        parseState = ParseMode::ValueError;
      }
    }
    if (parseState == ParseMode::Valid && possible_value[0] == ' ') {
      possible_value.remove_prefix(1);
    }
    return std::string(possible_value);
  }
};
