/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include <algorithm>
#include <functional>
#include <map>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

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

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

#include "cmsys/FStream.hxx"

#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"

namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using CacheVariable = cmCMakePresetsGraph::CacheVariable;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;

constexpr int MIN_VERSION = 1;
constexpr int MAX_VERSION = 4;

struct CMakeVersion
{
  unsigned int Major = 0;
  unsigned int Minor = 0;
  unsigned int Patch = 0;
};

struct RootPresets
{
  CMakeVersion CMakeMinimumRequired;
  std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets;
  std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets;
  std::vector<cmCMakePresetsGraph::TestPreset> TestPresets;
  std::vector<std::string> Include;
};

std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition(
  std::unique_ptr<cmCMakePresetsGraph::Condition> condition)
{
  auto retval = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
  retval->SubCondition = std::move(condition);
  return retval;
}

auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>(
  ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);

auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>(
  ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);

auto const ConditionStringListHelper =
  cmJSONVectorHelper<std::string, ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
    ConditionStringHelper);

auto const ConstConditionHelper =
  cmJSONObjectHelper<cmCMakePresetsGraphInternal::ConstCondition,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value,
          ConditionBoolHelper, true);

auto const EqualsConditionHelper =
  cmJSONObjectHelper<cmCMakePresetsGraphInternal::EqualsCondition,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs,
          ConditionStringHelper, true)
    .Bind("rhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Rhs,
          ConditionStringHelper, true);

auto const InListConditionHelper =
  cmJSONObjectHelper<cmCMakePresetsGraphInternal::InListCondition,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String,
          ConditionStringHelper, true)
    .Bind("list"_s, &cmCMakePresetsGraphInternal::InListCondition::List,
          ConditionStringListHelper, true);

auto const MatchesConditionHelper =
  cmJSONObjectHelper<cmCMakePresetsGraphInternal::MatchesCondition,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String,
          ConditionStringHelper, true)
    .Bind("regex"_s, &cmCMakePresetsGraphInternal::MatchesCondition::Regex,
          ConditionStringHelper, true);

ReadFileResult SubConditionHelper(
  std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
  const Json::Value* value);

auto const ListConditionVectorHelper =
  cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsGraph::Condition>,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION,
                                     SubConditionHelper);
auto const AnyAllOfConditionHelper =
  cmJSONObjectHelper<cmCMakePresetsGraphInternal::AnyAllOfCondition,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("conditions"_s,
          &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions,
          ListConditionVectorHelper);

auto const NotConditionHelper =
  cmJSONObjectHelper<cmCMakePresetsGraphInternal::NotCondition,
                     ReadFileResult>(ReadFileResult::READ_OK,
                                     ReadFileResult::INVALID_CONDITION, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("condition"_s,
          &cmCMakePresetsGraphInternal::NotCondition::SubCondition,
          SubConditionHelper);

ReadFileResult ConditionHelper(
  std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
  const Json::Value* value)
{
  if (!value) {
    out.reset();
    return ReadFileResult::READ_OK;
  }

  if (value->isBool()) {
    auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
    c->Value = value->asBool();
    out = std::move(c);
    return ReadFileResult::READ_OK;
  }

  if (value->isNull()) {
    out = cm::make_unique<cmCMakePresetsGraphInternal::NullCondition>();
    return ReadFileResult::READ_OK;
  }

  if (value->isObject()) {
    if (!value->isMember("type")) {
      return ReadFileResult::INVALID_CONDITION;
    }

    if (!(*value)["type"].isString()) {
      return ReadFileResult::INVALID_CONDITION;
    }
    auto type = (*value)["type"].asString();

    if (type == "const") {
      auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
      CHECK_OK(ConstConditionHelper(*c, value));
      out = std::move(c);
      return ReadFileResult::READ_OK;
    }

    if (type == "equals" || type == "notEquals") {
      auto c = cm::make_unique<cmCMakePresetsGraphInternal::EqualsCondition>();
      CHECK_OK(EqualsConditionHelper(*c, value));
      out = std::move(c);
      if (type == "notEquals") {
        out = InvertCondition(std::move(out));
      }
      return ReadFileResult::READ_OK;
    }

    if (type == "inList" || type == "notInList") {
      auto c = cm::make_unique<cmCMakePresetsGraphInternal::InListCondition>();
      CHECK_OK(InListConditionHelper(*c, value));
      out = std::move(c);
      if (type == "notInList") {
        out = InvertCondition(std::move(out));
      }
      return ReadFileResult::READ_OK;
    }

    if (type == "matches" || type == "notMatches") {
      auto c =
        cm::make_unique<cmCMakePresetsGraphInternal::MatchesCondition>();
      CHECK_OK(MatchesConditionHelper(*c, value));
      out = std::move(c);
      if (type == "notMatches") {
        out = InvertCondition(std::move(out));
      }
      return ReadFileResult::READ_OK;
    }

    if (type == "anyOf" || type == "allOf") {
      auto c =
        cm::make_unique<cmCMakePresetsGraphInternal::AnyAllOfCondition>();
      c->StopValue = (type == "anyOf");
      CHECK_OK(AnyAllOfConditionHelper(*c, value));
      out = std::move(c);
      return ReadFileResult::READ_OK;
    }

    if (type == "not") {
      auto c = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
      CHECK_OK(NotConditionHelper(*c, value));
      out = std::move(c);
      return ReadFileResult::READ_OK;
    }
  }

  return ReadFileResult::INVALID_CONDITION;
}

ReadFileResult SubConditionHelper(
  std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
  const Json::Value* value)
{
  std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
  auto result = ConditionHelper(ptr, value);
  if (ptr && ptr->IsNull()) {
    return ReadFileResult::INVALID_CONDITION;
  }
  out = std::move(ptr);
  return result;
}

ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
                                 const Json::Value* value)
{
  if (!value || value->isNull()) {
    out = cm::nullopt;
    return ReadFileResult::READ_OK;
  }
  if (value->isString()) {
    out = value->asString();
    return ReadFileResult::READ_OK;
  }
  return ReadFileResult::INVALID_PRESET;
}

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

auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
  ReadFileResult::NO_VERSION, VersionIntHelper);

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

auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
  ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);

auto const CMakeVersionHelper =
  cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
    .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
    .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
    .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);

auto const IncludeHelper = cmJSONStringHelper<ReadFileResult>(
  ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE);

auto const IncludeVectorHelper =
  cmJSONVectorHelper<std::string, ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper);

auto const RootPresetsHelper =
  cmJSONObjectHelper<RootPresets, ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
    .Bind<int>("version"_s, nullptr, VersionHelper)
    .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
          cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false)
    .Bind("buildPresets"_s, &RootPresets::BuildPresets,
          cmCMakePresetsGraphInternal::BuildPresetsHelper, false)
    .Bind("testPresets"_s, &RootPresets::TestPresets,
          cmCMakePresetsGraphInternal::TestPresetsHelper, false)
    .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
          CMakeVersionHelper, false)
    .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
    .Bind<std::nullptr_t>(
      "vendor"_s, nullptr,
      cmCMakePresetsGraphInternal::VendorHelper(ReadFileResult::INVALID_ROOT),
      false);
}

namespace cmCMakePresetsGraphInternal {
cmCMakePresetsGraph::ReadFileResult PresetStringHelper(
  std::string& out, const Json::Value* value)
{
  static auto const helper = cmJSONStringHelper<ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);

  return helper(out, value);
}

cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper(
  std::vector<std::string>& out, const Json::Value* value)
{
  static auto const helper = cmJSONVectorHelper<std::string, ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
    cmCMakePresetsGraphInternal::PresetStringHelper);

  return helper(out, value);
}

cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out,
                                                     const Json::Value* value)
{
  static auto const helper = cmJSONBoolHelper<ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);

  return helper(out, value);
}

cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper(
  cm::optional<bool>& out, const Json::Value* value)
{
  static auto const helper = cmJSONOptionalHelper<bool, ReadFileResult>(
    ReadFileResult::READ_OK, PresetBoolHelper);

  return helper(out, value);
}

cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out,
                                                    const Json::Value* value)
{
  static auto const helper = cmJSONIntHelper<ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);

  return helper(out, value);
}

cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper(
  cm::optional<int>& out, const Json::Value* value)
{
  static auto const helper = cmJSONOptionalHelper<int, ReadFileResult>(
    ReadFileResult::READ_OK, PresetIntHelper);

  return helper(out, value);
}

cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper(
  std::vector<int>& out, const Json::Value* value)
{
  static auto const helper = cmJSONVectorHelper<int, ReadFileResult>(
    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);

  return helper(out, value);
}

cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
{
  return [error](std::nullptr_t& /*out*/,
                 const Json::Value* value) -> ReadFileResult {
    if (!value) {
      return ReadFileResult::READ_OK;
    }

    if (!value->isObject()) {
      return error;
    }

    return ReadFileResult::READ_OK;
  };
}

ReadFileResult PresetConditionHelper(
  std::shared_ptr<cmCMakePresetsGraph::Condition>& out,
  const Json::Value* value)
{
  std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
  auto result = ConditionHelper(ptr, value);
  out = std::move(ptr);
  return result;
}

ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
                                                 const Json::Value* value)
{
  out.clear();
  if (!value) {
    return ReadFileResult::READ_OK;
  }

  if (value->isString()) {
    out.push_back(value->asString());
    return ReadFileResult::READ_OK;
  }

  return PresetVectorStringHelper(out, value);
}

cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
  std::map<std::string, cm::optional<std::string>>& out,
  const Json::Value* value)
{
  static auto const helper =
    cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
      ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
      EnvironmentHelper);

  return helper(out, value);
}
}

cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
  const std::string& filename, RootType rootType, ReadReason readReason,
  std::vector<File*>& inProgressFiles, File*& file)
{
  ReadFileResult result;

  for (auto const& f : this->Files) {
    if (cmSystemTools::SameFile(filename, f->Filename)) {
      file = f.get();
      auto fileIt =
        std::find(inProgressFiles.begin(), inProgressFiles.end(), file);
      if (fileIt != inProgressFiles.end()) {
        return cmCMakePresetsGraph::ReadFileResult::CYCLIC_INCLUDE;
      }

      return cmCMakePresetsGraph::ReadFileResult::READ_OK;
    }
  }

  cmsys::ifstream fin(filename.c_str());
  if (!fin) {
    return ReadFileResult::FILE_NOT_FOUND;
  }
  // If there's a BOM, toss it.
  cmsys::FStream::ReadBOM(fin);

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

  int v = 0;
  if ((result = RootVersionHelper(v, &root)) != ReadFileResult::READ_OK) {
    return result;
  }
  if (v < MIN_VERSION || v > MAX_VERSION) {
    return ReadFileResult::UNRECOGNIZED_VERSION;
  }

  // Support for build and test presets added in version 2.
  if (v < 2 &&
      (root.isMember("buildPresets") || root.isMember("testPresets"))) {
    return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
  }

  // Support for include added in version 4.
  if (v < 4 && root.isMember("include")) {
    return ReadFileResult::INCLUDE_UNSUPPORTED;
  }

  RootPresets presets;
  if ((result = RootPresetsHelper(presets, &root)) !=
      ReadFileResult::READ_OK) {
    return result;
  }

  unsigned int currentMajor = cmVersion::GetMajorVersion();
  unsigned int currentMinor = cmVersion::GetMinorVersion();
  unsigned int currentPatch = cmVersion::GetPatchVersion();
  auto const& required = presets.CMakeMinimumRequired;
  if (required.Major > currentMajor ||
      (required.Major == currentMajor &&
       (required.Minor > currentMinor ||
        (required.Minor == currentMinor &&
         (required.Patch > currentPatch))))) {
    return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
  }

  auto filePtr = cm::make_unique<File>();
  file = filePtr.get();
  this->Files.emplace_back(std::move(filePtr));
  inProgressFiles.emplace_back(file);
  file->Filename = filename;
  file->Version = v;
  file->ReachableFiles.insert(file);

  for (auto& preset : presets.ConfigurePresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      return ReadFileResult::INVALID_PRESET;
    }

    PresetPair<ConfigurePreset> presetPair;
    presetPair.Unexpanded = preset;
    presetPair.Expanded = cm::nullopt;
    if (!this->ConfigurePresets
           .emplace(std::make_pair(preset.Name, presetPair))
           .second) {
      return ReadFileResult::DUPLICATE_PRESETS;
    }

    // Support for installDir presets added in version 3.
    if (v < 3 && !preset.InstallDir.empty()) {
      return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
    }

    // Support for conditions added in version 3.
    if (v < 3 && preset.ConditionEvaluator) {
      return ReadFileResult::CONDITION_UNSUPPORTED;
    }

    // Support for toolchainFile presets added in version 3.
    if (v < 3 && !preset.ToolchainFile.empty()) {
      return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
    }

    this->ConfigurePresetOrder.push_back(preset.Name);
  }

  for (auto& preset : presets.BuildPresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      return ReadFileResult::INVALID_PRESET;
    }

    PresetPair<BuildPreset> presetPair;
    presetPair.Unexpanded = preset;
    presetPair.Expanded = cm::nullopt;
    if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
      return ReadFileResult::DUPLICATE_PRESETS;
    }

    // Support for conditions added in version 3.
    if (v < 3 && preset.ConditionEvaluator) {
      return ReadFileResult::CONDITION_UNSUPPORTED;
    }

    this->BuildPresetOrder.push_back(preset.Name);
  }

  for (auto& preset : presets.TestPresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      return ReadFileResult::INVALID_PRESET;
    }

    PresetPair<TestPreset> presetPair;
    presetPair.Unexpanded = preset;
    presetPair.Expanded = cm::nullopt;
    if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
      return ReadFileResult::DUPLICATE_PRESETS;
    }

    // Support for conditions added in version 3.
    if (v < 3 && preset.ConditionEvaluator) {
      return ReadFileResult::CONDITION_UNSUPPORTED;
    }

    this->TestPresetOrder.push_back(preset.Name);
  }

  auto const includeFile = [this, &inProgressFiles, file](
                             const std::string& include, RootType rootType2,
                             ReadReason readReason2) -> ReadFileResult {
    ReadFileResult r;
    File* includedFile;
    if ((r = this->ReadJSONFile(include, rootType2, readReason2,
                                inProgressFiles, includedFile)) !=
        ReadFileResult::READ_OK) {
      return r;
    }

    file->ReachableFiles.insert(includedFile->ReachableFiles.begin(),
                                includedFile->ReachableFiles.end());
    return ReadFileResult::READ_OK;
  };

  for (auto include : presets.Include) {
    if (!cmSystemTools::FileIsFullPath(include)) {
      auto directory = cmSystemTools::GetFilenamePath(filename);
      include = cmStrCat(directory, '/', include);
    }

    if ((result = includeFile(include, rootType, ReadReason::Included)) !=
        ReadFileResult::READ_OK) {
      return result;
    }
  }

  if (rootType == RootType::User && readReason == ReadReason::Root) {
    auto cmakePresetsFilename = GetFilename(this->SourceDir);
    if (cmSystemTools::FileExists(cmakePresetsFilename)) {
      if ((result = includeFile(cmakePresetsFilename, RootType::Project,
                                ReadReason::Root)) !=
          ReadFileResult::READ_OK) {
        return result;
      }
    }
  }

  inProgressFiles.pop_back();
  return ReadFileResult::READ_OK;
}
