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

#include "cmConfigure.h" // IWYU pragma: keep

#include <cassert>
#include <cstddef>
#include <functional>
#include <iterator>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include <cm/optional>
#include <cm/string_view>
#include <cm/type_traits>
#include <cmext/string_view>
#include <cmext/type_traits>

#include "cmArgumentParserTypes.h" // IWYU pragma: keep

template <typename Result>
class cmArgumentParser; // IWYU pragma: keep

class cmMakefile;

namespace ArgumentParser {

class ParseResult
{
  std::map<cm::string_view, std::string> KeywordErrors;

public:
  explicit operator bool() const { return this->KeywordErrors.empty(); }

  void AddKeywordError(cm::string_view key, cm::string_view text)

  {
    this->KeywordErrors[key] += text;
  }

  std::map<cm::string_view, std::string> const& GetKeywordErrors() const
  {
    return this->KeywordErrors;
  }

  bool MaybeReportError(cmMakefile& mf) const;
};

template <typename Result>
typename std::enable_if<std::is_base_of<ParseResult, Result>::value,
                        ParseResult*>::type
AsParseResultPtr(Result& result)
{
  return &result;
}

template <typename Result>
typename std::enable_if<!std::is_base_of<ParseResult, Result>::value,
                        ParseResult*>::type
AsParseResultPtr(Result&)
{
  return nullptr;
}

enum class Continue
{
  No,
  Yes,
};

struct ExpectAtLeast
{
  std::size_t Count = 0;

  ExpectAtLeast(std::size_t count)
    : Count(count)
  {
  }
};

class Instance;
using KeywordAction = std::function<void(Instance&)>;
using KeywordNameAction = std::function<void(Instance&, cm::string_view)>;
using PositionAction =
  std::function<void(Instance&, std::size_t, cm::string_view)>;

// using KeywordActionMap = cm::flat_map<cm::string_view, KeywordAction>;
class KeywordActionMap
  : public std::vector<std::pair<cm::string_view, KeywordAction>>
{
public:
  std::pair<iterator, bool> Emplace(cm::string_view name,
                                    KeywordAction action);
  const_iterator Find(cm::string_view name) const;
};

// using PositionActionMap = cm::flat_map<cm::string_view, PositionAction>;
class PositionActionMap
  : public std::vector<std::pair<std::size_t, PositionAction>>
{
public:
  std::pair<iterator, bool> Emplace(std::size_t pos, PositionAction action);
  const_iterator Find(std::size_t pos) const;
};

class ActionMap
{
public:
  KeywordActionMap Keywords;
  KeywordNameAction KeywordMissingValue;
  KeywordNameAction ParsedKeyword;
  PositionActionMap Positions;
  KeywordAction TrailingArgs;
};

class Base
{
public:
  using ExpectAtLeast = ArgumentParser::ExpectAtLeast;
  using Continue = ArgumentParser::Continue;
  using Instance = ArgumentParser::Instance;
  using ParseResult = ArgumentParser::ParseResult;

  ArgumentParser::ActionMap Bindings;

  bool MaybeBind(cm::string_view name, KeywordAction action)
  {
    return this->Bindings.Keywords.Emplace(name, std::move(action)).second;
  }

  void Bind(cm::string_view name, KeywordAction action)
  {
    bool const inserted = this->MaybeBind(name, std::move(action));
    assert(inserted);
    static_cast<void>(inserted);
  }

  void BindParsedKeyword(KeywordNameAction action)
  {
    assert(!this->Bindings.ParsedKeyword);
    this->Bindings.ParsedKeyword = std::move(action);
  }

  void BindKeywordMissingValue(KeywordNameAction action)
  {
    assert(!this->Bindings.KeywordMissingValue);
    this->Bindings.KeywordMissingValue = std::move(action);
  }

  void BindTrailingArgs(KeywordAction action)
  {
    assert(!this->Bindings.TrailingArgs);
    this->Bindings.TrailingArgs = std::move(action);
  }

  void Bind(std::size_t pos, PositionAction action)
  {
    bool const inserted =
      this->Bindings.Positions.Emplace(pos, std::move(action)).second;
    assert(inserted);
    static_cast<void>(inserted);
  }
};

class Instance
{
public:
  Instance(ActionMap const& bindings, ParseResult* parseResult,
           std::vector<std::string>* unparsedArguments, void* result = nullptr)
    : Bindings(bindings)
    , ParseResults(parseResult)
    , UnparsedArguments(unparsedArguments)
    , Result(result)
  {
  }

  void Bind(std::function<Continue(cm::string_view)> f, ExpectAtLeast expect);
  void Bind(bool& val);
  void Bind(std::string& val);
  void Bind(NonEmpty<std::string>& val);
  void Bind(Maybe<std::string>& val);
  void Bind(MaybeEmpty<std::vector<std::string>>& val);
  void Bind(NonEmpty<std::vector<std::string>>& val);
  void Bind(std::vector<std::vector<std::string>>& val);
  template <typename U>
  void Bind(NonEmpty<std::vector<std::pair<std::string, U>>>& val,
            U const& context)
  {
    this->Bind(
      [&val, &context](cm::string_view arg) -> Continue {
        val.emplace_back(std::string(arg), context);
        return Continue::Yes;
      },
      ExpectAtLeast{ 1 });
  }

  // cm::optional<> records the presence the keyword to which it binds.
  template <typename T>
  void Bind(cm::optional<T>& optVal)
  {
    if (!optVal) {
      optVal.emplace();
    }
    this->Bind(*optVal);
  }

  template <typename T, typename U>
  void Bind(cm::optional<T>& optVal, U const& context)
  {
    if (!optVal) {
      optVal.emplace();
    }
    this->Bind(*optVal, context);
  }

  template <typename Range>
  void Parse(Range const& args, std::size_t pos = 0)
  {
    for (cm::string_view arg : args) {
      this->Consume(pos++, arg);
    }
    this->FinishKeyword();
  }

private:
  ActionMap const& Bindings;
  ParseResult* ParseResults = nullptr;
  std::vector<std::string>* UnparsedArguments = nullptr;
  void* Result = nullptr;

  cm::string_view Keyword;
  std::size_t KeywordValuesSeen = 0;
  std::size_t KeywordValuesExpected = 0;
  std::function<Continue(cm::string_view)> KeywordValueFunc;
  bool DoneWithPositional = false;

  void Consume(std::size_t pos, cm::string_view arg);
  void FinishKeyword();

  template <typename Result>
  friend class ::cmArgumentParser;
};

} // namespace ArgumentParser

template <typename Result>
class cmArgumentParser : private ArgumentParser::Base
{
public:
  // I *think* this function could be made `constexpr` when the code is
  // compiled as C++20.  This would allow building a parser at compile time.
  template <typename T, typename cT = cm::member_pointer_class_t<T>,
            typename mT = cm::remove_member_pointer_t<T>,
            typename = cm::enable_if_t<std::is_base_of<cT, Result>::value>,
            typename = cm::enable_if_t<!std::is_function<mT>::value>>
  cmArgumentParser& Bind(cm::static_string_view name, T member)
  {
    this->Base::Bind(name, [member](Instance& instance) {
      instance.Bind(static_cast<Result*>(instance.Result)->*member);
    });
    return *this;
  }

  template <typename T, typename U>
  cmArgumentParser& BindWithContext(cm::static_string_view name,
                                    T Result::*member, U Result::*context)
  {
    this->Base::Bind(name, [member, context](Instance& instance) {
      auto* result = static_cast<Result*>(instance.Result);
      instance.Bind(result->*member, result->*context);
    });
    return *this;
  }

  cmArgumentParser& Bind(cm::static_string_view name,
                         Continue (Result::*member)(cm::string_view),
                         ExpectAtLeast expect = { 1 })
  {
    this->Base::Bind(name, [member, expect](Instance& instance) {
      Result* result = static_cast<Result*>(instance.Result);
      instance.Bind(
        [result, member](cm::string_view arg) -> Continue {
          return (result->*member)(arg);
        },
        expect);
    });
    return *this;
  }

  cmArgumentParser& Bind(cm::static_string_view name,
                         Continue (Result::*member)(cm::string_view,
                                                    cm::string_view),
                         ExpectAtLeast expect = { 1 })
  {
    this->Base::Bind(name, [member, expect](Instance& instance) {
      Result* result = static_cast<Result*>(instance.Result);
      cm::string_view keyword = instance.Keyword;
      instance.Bind(
        [result, member, keyword](cm::string_view arg) -> Continue {
          return (result->*member)(keyword, arg);
        },
        expect);
    });
    return *this;
  }

  cmArgumentParser& Bind(cm::static_string_view name,
                         std::function<Continue(Result&, cm::string_view)> f,
                         ExpectAtLeast expect = { 1 })
  {
    this->Base::Bind(name, [f, expect](Instance& instance) {
      Result* result = static_cast<Result*>(instance.Result);
      instance.Bind(
        [result, &f](cm::string_view arg) -> Continue {
          return f(*result, arg);
        },
        expect);
    });
    return *this;
  }

  cmArgumentParser& Bind(
    cm::static_string_view name,
    std::function<Continue(Result&, cm::string_view, cm::string_view)> f,
    ExpectAtLeast expect = { 1 })
  {
    this->Base::Bind(name, [f, expect](Instance& instance) {
      Result* result = static_cast<Result*>(instance.Result);
      cm::string_view keyword = instance.Keyword;
      instance.Bind(
        [result, keyword, &f](cm::string_view arg) -> Continue {
          return f(*result, keyword, arg);
        },
        expect);
    });
    return *this;
  }

  cmArgumentParser& Bind(std::size_t position,
                         cm::optional<std::string> Result::*member)
  {
    this->Base::Bind(
      position,
      [member](Instance& instance, std::size_t, cm::string_view arg) {
        Result* result = static_cast<Result*>(instance.Result);
        result->*member = arg;
      });
    return *this;
  }

  cmArgumentParser& BindParsedKeywords(
    std::vector<cm::string_view> Result::*member)
  {
    this->Base::BindParsedKeyword(
      [member](Instance& instance, cm::string_view arg) {
        (static_cast<Result*>(instance.Result)->*member).emplace_back(arg);
      });
    return *this;
  }

  template <typename T, typename cT = cm::member_pointer_class_t<T>,
            typename mT = cm::remove_member_pointer_t<T>,
            typename = cm::enable_if_t<std::is_base_of<cT, Result>::value>,
            typename = cm::enable_if_t<!std::is_function<mT>::value>>
  cmArgumentParser& BindTrailingArgs(T member)
  {
    this->Base::BindTrailingArgs([member](Instance& instance) {
      instance.Bind(static_cast<Result*>(instance.Result)->*member);
    });
    return *this;
  }

  template <typename Range>
  bool Parse(Result& result, Range const& args,
             std::vector<std::string>* unparsedArguments,
             std::size_t pos = 0) const
  {
    using ArgumentParser::AsParseResultPtr;
    ParseResult* parseResultPtr = AsParseResultPtr(result);
    Instance instance(this->Bindings, parseResultPtr, unparsedArguments,
                      &result);
    instance.Parse(args, pos);
    return parseResultPtr ? static_cast<bool>(*parseResultPtr) : true;
  }

  template <typename Range>
  Result Parse(Range const& args, std::vector<std::string>* unparsedArguments,
               std::size_t pos = 0) const
  {
    Result result;
    this->Parse(result, args, unparsedArguments, pos);
    return result;
  }
};

template <>
class cmArgumentParser<void> : private ArgumentParser::Base
{
public:
  template <typename T>
  cmArgumentParser& Bind(cm::static_string_view name, T& ref)
  {
    this->Base::Bind(name, [&ref](Instance& instance) { instance.Bind(ref); });
    return *this;
  }

  cmArgumentParser& Bind(cm::static_string_view name,
                         std::function<Continue(cm::string_view)> f,
                         ExpectAtLeast expect = { 1 })
  {
    this->Base::Bind(name, [f, expect](Instance& instance) {
      instance.Bind([&f](cm::string_view arg) -> Continue { return f(arg); },
                    expect);
    });
    return *this;
  }

  cmArgumentParser& Bind(
    cm::static_string_view name,
    std::function<Continue(cm::string_view, cm::string_view)> f,
    ExpectAtLeast expect = { 1 })
  {
    this->Base::Bind(name, [f, expect](Instance& instance) {
      cm::string_view keyword = instance.Keyword;
      instance.Bind(
        [keyword, &f](cm::string_view arg) -> Continue {
          return f(keyword, arg);
        },
        expect);
    });
    return *this;
  }

  cmArgumentParser& Bind(std::size_t position, cm::optional<std::string>& ref)
  {
    this->Base::Bind(position,
                     [&ref](Instance&, std::size_t, cm::string_view arg) {
                       ref = std::string(arg);
                     });
    return *this;
  }

  cmArgumentParser& BindParsedKeywords(std::vector<cm::string_view>& ref)
  {
    this->Base::BindParsedKeyword(
      [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); });
    return *this;
  }

  template <typename T>
  cmArgumentParser& BindTrailingArgs(T& ref)
  {
    this->Base::BindTrailingArgs(
      [&ref](Instance& instance) { instance.Bind(ref); });
    return *this;
  }

  template <typename Range>
  ParseResult Parse(Range const& args,
                    std::vector<std::string>* unparsedArguments,
                    std::size_t pos = 0) const
  {
    ParseResult parseResult;
    Instance instance(this->Bindings, &parseResult, unparsedArguments);
    instance.Parse(args, pos);
    return parseResult;
  }

protected:
  using Base::Instance;
  using Base::BindKeywordMissingValue;

  template <typename T>
  bool Bind(cm::string_view name, T& ref)
  {
    return this->MaybeBind(name,
                           [&ref](Instance& instance) { instance.Bind(ref); });
  }
};
