/* 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 <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

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

#include <cm3p/json/value.h>

#include "cmJSONState.h"
#include "cmStringAlgorithms.h"

template <typename T>
using cmJSONHelper =
  std::function<bool(T& out, Json::Value const* value, cmJSONState* state)>;

using ErrorGenerator = std::function<void(Json::Value const*, cmJSONState*)>;

namespace JsonErrors {
enum ObjectError
{
  RequiredMissing,
  InvalidObject,
  ExtraField,
  MissingRequired
};

using ErrorGenerator = std::function<void(Json::Value const*, cmJSONState*)>;
using ObjectErrorGenerator =
  std::function<ErrorGenerator(ObjectError, Json::Value::Members const&)>;

ErrorGenerator EXPECTED_TYPE(std::string const& type);

void INVALID_STRING(Json::Value const* value, cmJSONState* state);

void INVALID_BOOL(Json::Value const* value, cmJSONState* state);

void INVALID_INT(Json::Value const* value, cmJSONState* state);

void INVALID_UINT(Json::Value const* value, cmJSONState* state);

ObjectErrorGenerator INVALID_NAMED_OBJECT(
  std::function<std::string(Json::Value const*, cmJSONState*)> const&
    nameGenerator);

ErrorGenerator INVALID_OBJECT(ObjectError errorType,
                              Json::Value::Members const& extraFields);

ErrorGenerator INVALID_NAMED_OBJECT_KEY(
  ObjectError errorType, Json::Value::Members const& extraFields);
}

#if __cplusplus >= 201703L
namespace details {
// A meta-function to check if a given callable type
// can be called with the only string ref arg.
template <typename F, typename Enable = void>
struct is_bool_filter
{
  static constexpr bool value = false;
};

template <typename F>
struct is_bool_filter<F,
                      std::enable_if_t<std::is_same_v<
                        std::invoke_result_t<F, std::string const&>, bool>>>
{
  static constexpr bool value = true;
};
}
#endif

struct cmJSONHelperBuilder
{
  template <typename T>
  class Object
  {
  public:
    Object(JsonErrors::ObjectErrorGenerator error = JsonErrors::INVALID_OBJECT,
           bool allowExtra = true)
      : Error(std::move(error))
      , AllowExtra(allowExtra)
    {
    }

    template <typename U, typename M, typename F>
    Object& Bind(cm::string_view name, M U::*member, F func,
                 bool required = true)
    {
      return this->BindPrivate(
        name,
        [func, member](T& out, Json::Value const* value, cmJSONState* state)
          -> bool { return func(out.*member, value, state); },
        required);
    }
    template <typename M, typename F>
    Object& Bind(cm::string_view name, std::nullptr_t, F func,
                 bool required = true)
    {
      return this->BindPrivate(
        name,
        [func](T& /*out*/, Json::Value const* value,
               cmJSONState* state) -> bool {
          M dummy;
          return func(dummy, value, state);
        },
        required);
    }
    template <typename F>
    Object& Bind(cm::string_view name, F func, bool required = true)
    {
      return this->BindPrivate(name, MemberFunction(func), required);
    }

    bool operator()(T& out, Json::Value const* value, cmJSONState* state) const
    {
      Json::Value::Members extraFields;
      if (!value && this->AnyRequired) {
        Error(JsonErrors::ObjectError::RequiredMissing, extraFields)(value,
                                                                     state);
        return false;
      }
      if (value && !value->isObject()) {
        Error(JsonErrors::ObjectError::InvalidObject, extraFields)(value,
                                                                   state);
        return false;
      }
      if (value) {
        extraFields = value->getMemberNames();
      }

      if (state->allowComments) {
        extraFields.erase(
          std::remove(extraFields.begin(), extraFields.end(), "$comment"),
          extraFields.end());
      }

      bool success = true;
      for (auto const& m : this->Members) {
        std::string name(m.Name.data(), m.Name.size());
        state->push_stack(name, value);
        if (value && value->isMember(name)) {
          if (!m.Function(out, &(*value)[name], state)) {
            success = false;
          }
          extraFields.erase(
            std::find(extraFields.begin(), extraFields.end(), name));
        } else if (!m.Required) {
          if (!m.Function(out, nullptr, state)) {
            success = false;
          }
        } else {
          Error(JsonErrors::ObjectError::MissingRequired, extraFields)(value,
                                                                       state);
          success = false;
        }
        state->pop_stack();
      }

      if (!this->AllowExtra && !extraFields.empty()) {
        Error(JsonErrors::ObjectError::ExtraField, extraFields)(value, state);
        success = false;
      }
      return success;
    }

  private:
    // Not a true cmJSONHelper, it just happens to match the signature
    using MemberFunction = std::function<bool(T& out, Json::Value const* value,
                                              cmJSONState* state)>;
    struct Member
    {
      Member(cm::string_view name, MemberFunction func, bool required)
        : Name{ name }
        , Function{ std::move(func) }
        , Required{ required }
      {
      }
      cm::string_view Name;
      MemberFunction Function;
      bool Required;
    };
    std::vector<Member> Members;
    bool AnyRequired = false;
    JsonErrors::ObjectErrorGenerator Error;
    bool AllowExtra;

    Object& BindPrivate(cm::string_view name, MemberFunction&& func,
                        bool required)
    {
      this->Members.emplace_back(name, std::move(func), required);
      this->AnyRequired = this->AnyRequired || required;
      return *this;
    }
  };

  static cmJSONHelper<std::string> String(
    JsonErrors::ErrorGenerator const& error = JsonErrors::INVALID_STRING,
    std::string const& defval = "")
  {
    return [error, defval](std::string& out, Json::Value const* value,
                           cmJSONState* state) -> bool {
      if (!value) {
        out = defval;
        return true;
      }
      if (!value->isString()) {
        error(value, state);
        return false;
      }
      out = value->asString();
      return true;
    };
  };

  static cmJSONHelper<std::string> String(std::string const& defval)
  {
    return String(JsonErrors::INVALID_STRING, defval);
  };

  static cmJSONHelper<int> Int(
    JsonErrors::ErrorGenerator const& error = JsonErrors::INVALID_INT,
    int defval = 0)
  {
    return [error, defval](int& out, Json::Value const* value,
                           cmJSONState* state) -> bool {
      if (!value) {
        out = defval;
        return true;
      }
      if (!value->isInt()) {
        error(value, state);
        return false;
      }
      out = value->asInt();
      return true;
    };
  }

  static cmJSONHelper<int> Int(int defval)
  {
    return Int(JsonErrors::INVALID_INT, defval);
  };

  static cmJSONHelper<unsigned int> UInt(
    JsonErrors::ErrorGenerator const& error = JsonErrors::INVALID_UINT,
    unsigned int defval = 0)
  {
    return [error, defval](unsigned int& out, Json::Value const* value,
                           cmJSONState* state) -> bool {
      if (!value) {
        out = defval;
        return true;
      }
      if (!value->isUInt()) {
        error(value, state);
        return false;
      }
      out = value->asUInt();
      return true;
    };
  }

  static cmJSONHelper<unsigned int> UInt(unsigned int defval)
  {
    return UInt(JsonErrors::INVALID_UINT, defval);
  }

  static cmJSONHelper<bool> Bool(
    JsonErrors::ErrorGenerator const& error = JsonErrors::INVALID_BOOL,
    bool defval = false)
  {
    return [error, defval](bool& out, Json::Value const* value,
                           cmJSONState* state) -> bool {
      if (!value) {
        out = defval;
        return true;
      }
      if (!value->isBool()) {
        error(value, state);
        return false;
      }
      out = value->asBool();
      return true;
    };
  }

  static cmJSONHelper<bool> Bool(bool defval)
  {
    return Bool(JsonErrors::INVALID_BOOL, defval);
  }

  template <typename T, typename F, typename Filter>
  static cmJSONHelper<std::vector<T>> VectorFilter(
    JsonErrors::ErrorGenerator const& error, F func, Filter filter)
  {
    return [error, func, filter](std::vector<T>& out, Json::Value const* value,
                                 cmJSONState* state) -> bool {
      bool success = true;
      if (!value) {
        out.clear();
        return true;
      }
      if (!value->isArray()) {
        error(value, state);
        return false;
      }
      out.clear();
      int index = 0;
      for (auto const& item : *value) {
        state->push_stack(cmStrCat("$vector_item_", index++), &item);
        T t;
        if (!func(t, &item, state)) {
          success = false;
        }
        if (!filter(t)) {
          state->pop_stack();
          continue;
        }
        out.push_back(std::move(t));
        state->pop_stack();
      }
      return success;
    };
  }

  template <typename T, typename F>
  static cmJSONHelper<std::vector<T>> Vector(JsonErrors::ErrorGenerator error,
                                             F func)
  {
    return VectorFilter<T, F>(std::move(error), func,
                              [](T const&) { return true; });
  }

  enum class FilterResult
  {
    Continue, ///< A filter has accepted a given key (and value)
    Skip,     ///< A filter has rejected a given key (or value)
    Error     ///< A filter has found and reported an error
  };

  /// Iterate over the object's members and call a filter callable to
  /// decide what to do with the current key/value.
  /// A filter returns one of the `FilterResult` values.
  /// A container type is an associative or a sequence
  /// container of pairs (key, value).
  template <typename Container, typename F, typename Filter>
  static cmJSONHelper<Container> FilteredObject(
    JsonErrors::ErrorGenerator const& error, F func, Filter filter)
  {
    return [error, func, filter](Container& out, Json::Value const* value,
                                 cmJSONState* state) -> bool {
      // NOTE Some compile-time code path don't use `filter` at all.
      // So, suppress "unused lambda capture" warning is needed.
      static_cast<void>(filter);

      if (!value) {
        out.clear();
        return true;
      }
      if (!value->isObject()) {
        error(value, state);
        return false;
      }
      out.clear();
      auto outIt = std::inserter(out, out.end());
      bool success = true;
      for (auto const& key : value->getMemberNames()) {
        state->push_stack(key, &(*value)[key]);
#if __cplusplus >= 201703L
        if constexpr (std::is_same_v<Filter, std::true_type>) {
          // Filtering functionality isn't needed at all...
        } else if constexpr (details::is_bool_filter<Filter>::value) {
          // A given `Filter` is `bool(const std::string&)` callable.
          if (!filter(key)) {
            state->pop_stack();
            continue;
          }
        } else {
#endif
          // A full-featured `Filter` has been given
          auto res = filter(key, &(*value)[key], state);
          if (res == FilterResult::Skip) {
            state->pop_stack();
            continue;
          }
          if (res == FilterResult::Error) {
            state->pop_stack();
            success = false;
            break;
          }
#if __cplusplus >= 201703L
        }
#endif
        typename Container::value_type::second_type t;
        // ATTENTION Call the function first (for it's side-effects),
        // then accumulate the result!
        success = func(t, &(*value)[key], state) && success;
        outIt = typename Container::value_type{ key, std::move(t) };
        state->pop_stack();
      }
      return success;
    };
  }

  template <typename T, typename F, typename Filter>
  static cmJSONHelper<std::map<std::string, T>> MapFilter(
    JsonErrors::ErrorGenerator const& error, F func, Filter filter)
  {
    // clang-format off
    return FilteredObject<std::map<std::string, T>>(
      error, func,
#if __cplusplus >= 201703L
      // In C++ 17 a filter callable can be passed as is.
      // Depending on its type `FilteredObject()` will call
      // it with a key only (backward compatible behavior)
      // or with 3 args supported by the full-featured
      // filtering feature.
      filter
#else
      // For C++14 and below, to keep backward compatibility
      // with CMake Presets code, `MapFilter()` can accept only
      // `bool(const std::string&)` callables.
      [filter](const std::string &key, const Json::Value * /*value*/,
              cmJSONState * /*state*/) -> FilterResult {
        // Simple adaptor to translate `bool` to `FilterResult`
        return filter(key) ? FilterResult::Continue : FilterResult::Skip;
      }
#endif
    );
    // clang-format on
  }

  template <typename T, typename F>
  static cmJSONHelper<std::map<std::string, T>> Map(
    JsonErrors::ErrorGenerator const& error, F func)
  {
    // clang-format off
    return FilteredObject<std::map<std::string, T>>(
      error, func,
#if __cplusplus >= 201703L
      // With C++ 17 and above, pass a marker type, that no
      // filtering is needed at all.
      std::true_type()
#else
      // In C++ 14 and below, pass an always-true dummy functor.
      [](const std::string& /*key*/, const Json::Value* /*value*/,
         cmJSONState* /*state*/) -> FilterResult {
        return FilterResult::Continue;
      }
#endif
    );
    // clang-format on
  }

  template <typename T, typename F>
  static cmJSONHelper<cm::optional<T>> Optional(F func)
  {
    return [func](cm::optional<T>& out, Json::Value const* value,
                  cmJSONState* state) -> bool {
      if (!value) {
        out.reset();
        return true;
      }
      out.emplace();
      return func(*out, value, state);
    };
  }

  template <typename T, typename F>
  static cmJSONHelper<T> Required(JsonErrors::ErrorGenerator const& error,
                                  F func)
  {
    return [error, func](T& out, Json::Value const* value,
                         cmJSONState* state) -> bool {
      if (!value) {
        error(value, state);
        return false;
      }
      return func(out, value, state);
    };
  }

  template <typename T, typename F, typename P>
  static cmJSONHelper<T> Checked(JsonErrors::ErrorGenerator const& error,
                                 F func, P predicate)
  {
    return [error, func, predicate](T& out, Json::Value const* value,
                                    cmJSONState* state) -> bool {
      bool result = func(out, value, state);
      if (result && !predicate(out)) {
        error(value, state);
        result = false;
      }
      return result;
    };
  }
};
