/* 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 <cstddef>
#include <functional>
#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;
    };
  }
};
