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

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

#include <cmext/string_view>

#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cmJSONHelpers.h"

namespace {
const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };

struct Version
{
  int Major = 1;
  int Minor = 0;
};

struct TopVersion
{
  struct Version Version;
};

auto const VersionFieldHelper =
  cmJSONIntHelper<cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_VERSION);

auto const VersionHelper =
  cmJSONRequiredHelper<Version, cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::NO_VERSION,
    cmJSONObjectHelper<Version, cmCTestResourceSpec::ReadFileResult>(
      cmCTestResourceSpec::ReadFileResult::READ_OK,
      cmCTestResourceSpec::ReadFileResult::INVALID_VERSION)
      .Bind("major"_s, &Version::Major, VersionFieldHelper)
      .Bind("minor"_s, &Version::Minor, VersionFieldHelper));

auto const RootVersionHelper =
  cmJSONObjectHelper<TopVersion, cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_ROOT)
    .Bind("version"_s, &TopVersion::Version, VersionHelper, false);

cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out,
                                                     const Json::Value* value)
{
  auto result = cmJSONStringHelper(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)(out, value);
  if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
    return result;
  }
  cmsys::RegularExpressionMatch match;
  if (!IdRegex.find(out.c_str(), match)) {
    return cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE;
  }
  return cmCTestResourceSpec::ReadFileResult::READ_OK;
}

auto const ResourceHelper =
  cmJSONObjectHelper<cmCTestResourceSpec::Resource,
                     cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)
    .Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper)
    .Bind("slots"_s, &cmCTestResourceSpec::Resource::Capacity,
          cmJSONUIntHelper(
            cmCTestResourceSpec::ReadFileResult::READ_OK,
            cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, 1),
          false);

auto const ResourceListHelper =
  cmJSONVectorHelper<cmCTestResourceSpec::Resource,
                     cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE,
    ResourceHelper);

auto const ResourceMapHelper =
  cmJSONMapFilterHelper<std::vector<cmCTestResourceSpec::Resource>,
                        cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
    ResourceListHelper, [](const std::string& key) -> bool {
      cmsys::RegularExpressionMatch match;
      return IdentifierRegex.find(key.c_str(), match);
    });

auto const SocketSetHelper = cmJSONVectorHelper<
  std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>(
  cmCTestResourceSpec::ReadFileResult::READ_OK,
  cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceMapHelper);

cmCTestResourceSpec::ReadFileResult SocketHelper(
  cmCTestResourceSpec::Socket& out, const Json::Value* value)
{
  std::vector<
    std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>
    sockets;
  cmCTestResourceSpec::ReadFileResult result = SocketSetHelper(sockets, value);
  if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
    return result;
  }
  if (sockets.size() > 1) {
    return cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC;
  }
  if (sockets.empty()) {
    out.Resources.clear();
  } else {
    out.Resources = std::move(sockets[0]);
  }
  return cmCTestResourceSpec::ReadFileResult::READ_OK;
}

auto const LocalRequiredHelper =
  cmJSONRequiredHelper<cmCTestResourceSpec::Socket,
                       cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper);

auto const RootHelper =
  cmJSONObjectHelper<cmCTestResourceSpec, cmCTestResourceSpec::ReadFileResult>(
    cmCTestResourceSpec::ReadFileResult::READ_OK,
    cmCTestResourceSpec::ReadFileResult::INVALID_ROOT)
    .Bind("local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper,
          false);
}

cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile(
  const std::string& filename)
{
  cmsys::ifstream fin(filename.c_str());
  if (!fin) {
    return ReadFileResult::FILE_NOT_FOUND;
  }

  Json::Value root;
  Json::CharReaderBuilder builder;
  if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
    return ReadFileResult::JSON_PARSE_ERROR;
  }

  TopVersion version;
  ReadFileResult result;
  if ((result = RootVersionHelper(version, &root)) !=
      ReadFileResult::READ_OK) {
    return result;
  }
  if (version.Version.Major != 1 || version.Version.Minor != 0) {
    return ReadFileResult::UNSUPPORTED_VERSION;
  }

  return RootHelper(*this, &root);
}

const char* cmCTestResourceSpec::ResultToString(ReadFileResult result)
{
  switch (result) {
    case ReadFileResult::READ_OK:
      return "OK";

    case ReadFileResult::FILE_NOT_FOUND:
      return "File not found";

    case ReadFileResult::JSON_PARSE_ERROR:
      return "JSON parse error";

    case ReadFileResult::INVALID_ROOT:
      return "Invalid root object";

    case ReadFileResult::NO_VERSION:
      return "No version specified";

    case ReadFileResult::INVALID_VERSION:
      return "Invalid version object";

    case ReadFileResult::UNSUPPORTED_VERSION:
      return "Unsupported version";

    case ReadFileResult::INVALID_SOCKET_SPEC:
      return "Invalid socket object";

    case ReadFileResult::INVALID_RESOURCE_TYPE:
      return "Invalid resource type object";

    case ReadFileResult::INVALID_RESOURCE:
      return "Invalid resource object";

    default:
      return "Unknown";
  }
}

bool cmCTestResourceSpec::operator==(const cmCTestResourceSpec& other) const
{
  return this->LocalSocket == other.LocalSocket;
}

bool cmCTestResourceSpec::operator!=(const cmCTestResourceSpec& other) const
{
  return !(*this == other);
}

bool cmCTestResourceSpec::Socket::operator==(
  const cmCTestResourceSpec::Socket& other) const
{
  return this->Resources == other.Resources;
}

bool cmCTestResourceSpec::Socket::operator!=(
  const cmCTestResourceSpec::Socket& other) const
{
  return !(*this == other);
}

bool cmCTestResourceSpec::Resource::operator==(
  const cmCTestResourceSpec::Resource& other) const
{
  return this->Id == other.Id && this->Capacity == other.Capacity;
}

bool cmCTestResourceSpec::Resource::operator!=(
  const cmCTestResourceSpec::Resource& other) const
{
  return !(*this == other);
}
