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

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

#include "cm_static_string_view.hxx"
#include "cm_string_view.hxx"

#include <cassert>
#include <functional>
#include <string>
#include <utility>
#include <vector>

namespace ArgumentParser {

using StringList = std::vector<std::string>;
using MultiStringList = std::vector<StringList>;

class Instance;
using Action = std::function<void(Instance&, void*)>;

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

class Instance
{
public:
  Instance(ActionMap const& bindings)
    : Bindings(bindings)
  {
  }

  void Bind(bool& val);
  void Bind(std::string& val);
  void Bind(StringList& val);
  void Bind(MultiStringList& val);

  void Consume(cm::string_view arg, void* result,
               std::vector<std::string>* unparsedArguments,
               std::vector<std::string>* keywordsMissingValue);

private:
  ActionMap const& Bindings;
  std::string* CurrentString = nullptr;
  StringList* CurrentList = nullptr;
  bool ExpectValue = false;
};

} // namespace ArgumentParser

template <typename Result>
class cmArgumentParser
{
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>
  cmArgumentParser& Bind(cm::static_string_view name, T Result::*member)
  {
    bool const inserted =
      this->Bindings
        .Emplace(name,
                 [member](ArgumentParser::Instance& instance, void* result) {
                   instance.Bind(static_cast<Result*>(result)->*member);
                 })
        .second;
    assert(inserted), (void)inserted;
    return *this;
  }

  template <typename Range>
  void Parse(Result& result, Range const& args,
             std::vector<std::string>* unparsedArguments = nullptr,
             std::vector<std::string>* keywordsMissingValue = nullptr) const
  {
    ArgumentParser::Instance instance(this->Bindings);
    for (cm::string_view arg : args) {
      instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue);
    }
  }

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

private:
  ArgumentParser::ActionMap Bindings;
};

template <>
class cmArgumentParser<void>
{
public:
  template <typename T>
  cmArgumentParser& Bind(cm::static_string_view name, T& ref)
  {
    bool const inserted = this->Bind(cm::string_view(name), ref);
    assert(inserted), (void)inserted;
    return *this;
  }

  template <typename Range>
  void Parse(Range const& args,
             std::vector<std::string>* unparsedArguments = nullptr,
             std::vector<std::string>* keywordsMissingValue = nullptr) const
  {
    ArgumentParser::Instance instance(this->Bindings);
    for (cm::string_view arg : args) {
      instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue);
    }
  }

protected:
  template <typename T>
  bool Bind(cm::string_view name, T& ref)
  {
    return this->Bindings
      .Emplace(name,
               [&ref](ArgumentParser::Instance& instance, void*) {
                 instance.Bind(ref);
               })
      .second;
  }

private:
  ArgumentParser::ActionMap Bindings;
};

#endif
