/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include <algorithm>
#include <cstddef>
#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/value.h>

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

namespace {
using CacheVariable = cmCMakePresetsGraph::CacheVariable;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
using PackagePreset = cmCMakePresetsGraph::PackagePreset;
using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
using JSONHelperBuilder = cmJSONHelperBuilder;
using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector;
using cmCMakePresetsGraphInternal::BaseMacroExpander;
using cmCMakePresetsGraphInternal::ExpandMacros;
using cmCMakePresetsGraphInternal::ExpandImmediateMacros;

constexpr int MIN_VERSION = 1;
constexpr int MAX_VERSION = 12;

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

struct RootPresets
{
  CMakeVersion CMakeMinimumRequired;
  std::vector<ConfigurePreset> ConfigurePresets;
  std::vector<BuildPreset> BuildPresets;
  std::vector<TestPreset> TestPresets;
  std::vector<PackagePreset> PackagePresets;
  std::vector<WorkflowPreset> WorkflowPresets;
  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 = JSONHelperBuilder::String();

auto const ConditionBoolHelper = JSONHelperBuilder::Bool();

auto const ConditionStringListHelper = JSONHelperBuilder::Vector<std::string>(
  cmCMakePresetsErrors::INVALID_CONDITION, ConditionStringHelper);

auto const ConstConditionHelper =
  JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::ConstCondition>(
    cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value,
          ConditionBoolHelper, true);

auto const EqualsConditionHelper =
  JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::EqualsCondition>(
    cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, 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 =
  JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::InListCondition>(
    cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, 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 =
  JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::MatchesCondition>(
    cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, 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);

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

auto const ListConditionVectorHelper =
  JSONHelperBuilder::Vector<std::unique_ptr<cmCMakePresetsGraph::Condition>>(
    cmCMakePresetsErrors::INVALID_CONDITION, SubConditionHelper);
auto const AnyAllOfConditionHelper =
  JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::AnyAllOfCondition>(
    cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("conditions"_s,
          &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions,
          ListConditionVectorHelper);

auto const NotConditionHelper =
  JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::NotCondition>(
    cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false)
    .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
    .Bind("condition"_s,
          &cmCMakePresetsGraphInternal::NotCondition::SubCondition,
          SubConditionHelper);

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

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

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

  if (value->isObject()) {
    if (!value->isMember("type")) {
      cmCMakePresetsErrors::INVALID_CONDITION(value, state);
      return false;
    }

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

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

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

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

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

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

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

  cmCMakePresetsErrors::INVALID_CONDITION(value, state);
  return false;
}

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

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

auto const VersionIntHelper =
  JSONHelperBuilder::Int(cmCMakePresetsErrors::INVALID_VERSION);

auto const VersionHelper = JSONHelperBuilder::Required<int>(
  cmCMakePresetsErrors::NO_VERSION, VersionIntHelper);

auto const VersionRangeHelper = JSONHelperBuilder::Checked<int>(
  cmCMakePresetsErrors::UNRECOGNIZED_VERSION_RANGE(MIN_VERSION, MAX_VERSION),
  VersionHelper,
  [](int const v) -> bool { return v >= MIN_VERSION && v <= MAX_VERSION; });

auto const RootVersionHelper =
  JSONHelperBuilder::Object<int>(cmCMakePresetsErrors::INVALID_ROOT_OBJECT)
    .Bind("version"_s, VersionRangeHelper, false);

auto const CMakeVersionUIntHelper =
  JSONHelperBuilder::UInt(cmCMakePresetsErrors::INVALID_VERSION);

auto const CMakeVersionHelper =
  JSONHelperBuilder::Object<CMakeVersion>(JsonErrors::INVALID_NAMED_OBJECT_KEY,
                                          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 =
  JSONHelperBuilder::String(cmCMakePresetsErrors::INVALID_INCLUDE);

auto const IncludeVectorHelper = JSONHelperBuilder::Vector<std::string>(
  cmCMakePresetsErrors::INVALID_INCLUDE, IncludeHelper);

auto const RootPresetsHelper =
  JSONHelperBuilder::Object<RootPresets>(
    cmCMakePresetsErrors::INVALID_ROOT_OBJECT, 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("packagePresets"_s, &RootPresets::PackagePresets,
          cmCMakePresetsGraphInternal::PackagePresetsHelper, false)
    .Bind("workflowPresets"_s, &RootPresets::WorkflowPresets,
          cmCMakePresetsGraphInternal::WorkflowPresetsHelper, false)
    .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
          CMakeVersionHelper, false)
    .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
    .Bind<std::nullptr_t>("vendor"_s, nullptr,
                          cmCMakePresetsGraphInternal::VendorHelper(
                            cmCMakePresetsErrors::INVALID_ROOT),
                          false)
    .Bind<std::nullptr_t>("$schema"_s, nullptr,
                          cmCMakePresetsGraphInternal::SchemaHelper(), false);

class EnvironmentMacroExpander : public MacroExpander
{
public:
  ExpandMacroResult operator()(std::string const& macroNamespace,
                               std::string const& macroName,
                               std::string& macroOut,
                               int /*version*/) const override
  {
    if (macroNamespace == "penv") {
      if (macroName.empty()) {
        return ExpandMacroResult::Error;
      }
      if (cm::optional<std::string> value =
            cmSystemTools::GetEnvVar(macroName)) {
        macroOut += *value;
      }
      return ExpandMacroResult::Ok;
    }

    return ExpandMacroResult::Ignore;
  }
};
}

namespace cmCMakePresetsGraphInternal {
bool PresetStringHelper(std::string& out, Json::Value const* value,
                        cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::String();
  return helper(out, value, state);
}

bool PresetNameHelper(std::string& out, Json::Value const* value,
                      cmJSONState* state)
{
  if (!value || !value->isString() || value->asString().empty()) {
    cmCMakePresetsErrors::INVALID_PRESET_NAME(value, state);
    return false;
  }
  out = value->asString();
  return true;
}

bool PresetVectorStringHelper(std::vector<std::string>& out,
                              Json::Value const* value, cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::Vector<std::string>(
    cmCMakePresetsErrors::INVALID_PRESET,
    cmCMakePresetsGraphInternal::PresetStringHelper);
  return helper(out, value, state);
}

bool PresetBoolHelper(bool& out, Json::Value const* value, cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::Bool();
  return helper(out, value, state);
}

bool PresetOptionalBoolHelper(cm::optional<bool>& out,
                              Json::Value const* value, cmJSONState* state)
{
  static auto const helper =
    JSONHelperBuilder::Optional<bool>(PresetBoolHelper);
  return helper(out, value, state);
}

bool PresetIntHelper(int& out, Json::Value const* value, cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::Int();
  return helper(out, value, state);
}

bool PresetOptionalIntHelper(cm::optional<int>& out, Json::Value const* value,
                             cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::Optional<int>(PresetIntHelper);
  return helper(out, value, state);
}

bool PresetUIntHelper(unsigned int& out, Json::Value const* value,
                      cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::UInt();
  return helper(out, value, state);
}

bool PresetOptionalUIntHelper(cm::optional<unsigned int>& out,
                              Json::Value const* value, cmJSONState* state)
{
  static auto const helper =
    JSONHelperBuilder::Optional<unsigned int>(PresetUIntHelper);
  return helper(out, value, state);
}

bool PresetVectorIntHelper(std::vector<int>& out, Json::Value const* value,
                           cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::Vector<int>(
    cmCMakePresetsErrors::INVALID_PRESET, PresetIntHelper);
  return helper(out, value, state);
}

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

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

    return true;
  };
}

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

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

  if (value->isString()) {
    out.push_back(value->asString());
    return true;
  }

  return PresetVectorStringHelper(out, value, state);
}

bool EnvironmentMapHelper(
  std::map<std::string, cm::optional<std::string>>& out,
  Json::Value const* value, cmJSONState* state)
{
  static auto const helper = JSONHelperBuilder::Map<cm::optional<std::string>>(
    cmCMakePresetsErrors::INVALID_PRESET, EnvironmentHelper);

  return helper(out, value, state);
}

cmJSONHelper<std::nullptr_t> SchemaHelper()
{
  return [](std::nullptr_t&, Json::Value const*, cmJSONState*) -> bool {
    return true;
  };
}
}

bool cmCMakePresetsGraph::ReadJSONFile(std::string const& filename,
                                       RootType rootType,
                                       ReadReason readReason,
                                       std::vector<File*>& inProgressFiles,
                                       File*& file, std::string& errMsg)
{
  bool 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()) {
        cmCMakePresetsErrors::CYCLIC_INCLUDE(filename, &this->parseState);
        return false;
      }

      return true;
    }
  }

  Json::Value root;
  this->parseState = cmJSONState(filename, &root);
  if (!this->parseState.errors.empty()) {
    return false;
  }

  int v = 0;
  if ((result = RootVersionHelper(v, &root, &parseState)) != true) {
    return result;
  }

  // Support for build and test presets added in version 2.
  if (v < 2) {
    if (root.isMember("buildPresets")) {
      cmCMakePresetsErrors::BUILD_TEST_PRESETS_UNSUPPORTED(
        &root["buildPresets"], &this->parseState);
      return false;
    }
    if (root.isMember("testPresets")) {
      cmCMakePresetsErrors::BUILD_TEST_PRESETS_UNSUPPORTED(
        &root["testPresets"], &this->parseState);
      return false;
    }
  }

  // Support for package presets added in version 6.
  if (v < 6 && root.isMember("packagePresets")) {
    cmCMakePresetsErrors::PACKAGE_PRESETS_UNSUPPORTED(&root["packagePresets"],
                                                      &this->parseState);
    return false;
  }

  // Support for workflow presets added in version 6.
  if (v < 6 && root.isMember("workflowPresets")) {
    cmCMakePresetsErrors::WORKFLOW_PRESETS_UNSUPPORTED(
      &root["workflowPresets"], &this->parseState);
    return false;
  }

  // Support for include added in version 4.
  if (v < 4 && root.isMember("include")) {
    cmCMakePresetsErrors::INCLUDE_UNSUPPORTED(&root["include"],
                                              &this->parseState);
    return false;
  }

  // Support for $schema added in version 8.
  if (v < 8 && root.isMember("$schema")) {
    cmCMakePresetsErrors::SCHEMA_UNSUPPORTED(&this->parseState);
    return false;
  }

  // Support for $comment added in version 10.
  this->parseState.allowComments = (v >= 10);

  RootPresets presets;
  if ((result = RootPresetsHelper(presets, &root, &parseState)) != true) {
    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) {
    ErrorGenerator error = cmCMakePresetsErrors::UNRECOGNIZED_CMAKE_VERSION(
      "major", currentMajor, required.Major);
    error(&root["cmakeMinimumRequired"]["major"], &this->parseState);
    return false;
  }
  if (required.Major == currentMajor) {
    if (required.Minor > currentMinor) {
      ErrorGenerator error = cmCMakePresetsErrors::UNRECOGNIZED_CMAKE_VERSION(
        "minor", currentMinor, required.Minor);
      error(&root["cmakeMinimumRequired"]["minor"], &this->parseState);
      return false;
    }
    if (required.Minor == currentMinor && required.Patch > currentPatch) {
      ErrorGenerator error = cmCMakePresetsErrors::UNRECOGNIZED_CMAKE_VERSION(
        "patch", currentPatch, required.Patch);
      error(&root["cmakeMinimumRequired"]["patch"], &this->parseState);
      return false;
    }
  }

  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()) {
      // No error, already handled by PresetNameHelper
      return false;
    }

    if (!ExpandImmediateMacros<ConfigurePreset>(preset)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
                                                    &this->parseState);
      return false;
    }

    // Support for installDir presets added in version 3.
    if (v < 3 && !preset.InstallDir.empty()) {
      cmCMakePresetsErrors::INSTALL_PREFIX_UNSUPPORTED(&root["installDir"],
                                                       &this->parseState);
      return false;
    }

    // Support for conditions added in version 3.
    if (v < 3 && preset.ConditionEvaluator) {
      cmCMakePresetsErrors::CONDITION_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for toolchainFile presets added in version 3.
    if (v < 3 && !preset.ToolchainFile.empty()) {
      cmCMakePresetsErrors::TOOLCHAIN_FILE_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for trace presets added in version 7.
    if (v < 7 &&
        (preset.TraceMode.has_value() || preset.TraceFormat.has_value() ||
         !preset.TraceRedirect.empty() || !preset.TraceSource.empty())) {
      cmCMakePresetsErrors::TRACE_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for graphviz argument added in version 10.
    if (v < 10 && !preset.GraphVizFile.empty()) {
      cmCMakePresetsErrors::GRAPHVIZ_FILE_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for diagnostics.
    if (!cmCMakePresetsGraphInternal::CheckDiagnostics(&this->parseState, v,
                                                       preset)) {
      return false;
    }

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

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

  for (auto& preset : presets.BuildPresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      // No error, already handled by PresetNameHelper
      return false;
    }

    if (!ExpandImmediateMacros<BuildPreset>(preset)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
                                                    &this->parseState);
      return false;
    }

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

    // Support for conditions added in version 3.
    if (v < 3 && preset.ConditionEvaluator) {
      cmCMakePresetsErrors::CONDITION_UNSUPPORTED(&this->parseState);
      return false;
    }

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

  for (auto& preset : presets.TestPresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      // No error, already handled by PresetNameHelper
      return false;
    }

    if (!ExpandImmediateMacros<TestPreset>(preset)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
                                                    &this->parseState);
      return false;
    }

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

    // Support for conditions added in version 3.
    if (v < 3 && preset.ConditionEvaluator) {
      cmCMakePresetsErrors::CONDITION_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for TestOutputTruncation added in version 5.
    if (v < 5 && preset.Output && preset.Output->TestOutputTruncation) {
      cmCMakePresetsErrors::TEST_OUTPUT_TRUNCATION_UNSUPPORTED(
        &this->parseState);
      return false;
    }

    // Support for outputJUnitFile added in version 6.
    if (v < 6 && preset.Output && !preset.Output->OutputJUnitFile.empty()) {
      cmCMakePresetsErrors::CTEST_JUNIT_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for processor-count-based jobs added in version 11.
    if (v < 11 && preset.Execution && preset.Execution->Jobs.has_value() &&
        !preset.Execution->Jobs->has_value()) {
      cmCMakePresetsErrors::JOBS_PROC_UNSUPPORTED(&this->parseState);
      return false;
    }

    // Support for testPassthroughArguments added in version 12.
    if (v < 12 && preset.Execution &&
        !preset.Execution->TestPassthroughArguments.empty()) {
      cmCMakePresetsErrors::PASSTHROUGH_ARGS_UNSUPPORTED(&this->parseState);
      return false;
    }

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

  for (auto& preset : presets.PackagePresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      // No error, already handled by PresetNameHelper
      return false;
    }

    if (!ExpandImmediateMacros<PackagePreset>(preset)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
                                                    &this->parseState);
      return false;
    }

    PresetPair<PackagePreset> presetPair;
    presetPair.Unexpanded = preset;
    presetPair.Expanded = cm::nullopt;
    if (!this->PackagePresets.emplace(preset.Name, presetPair).second) {
      cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
      return false;
    }

    // Support for conditions added in version 3, but this requires version 5
    // already, so no action needed.

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

  for (auto& preset : presets.WorkflowPresets) {
    preset.OriginFile = file;
    if (preset.Name.empty()) {
      // No error, already handled by PresetNameHelper
      return false;
    }

    if (!ExpandImmediateMacros<WorkflowPreset>(preset)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name,
                                                    &this->parseState);
      return false;
    }

    PresetPair<WorkflowPreset> presetPair;
    presetPair.Unexpanded = preset;
    presetPair.Expanded = cm::nullopt;
    if (!this->WorkflowPresets.emplace(preset.Name, presetPair).second) {
      cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
      return false;
    }

    // Support for conditions added in version 3, but this requires version 6
    // already, so no action needed.

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

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

    file->ReachableFiles.insert(includedFile->ReachableFiles.begin(),
                                includedFile->ReachableFiles.end());
    return true;
  };

  MacroExpanderVector macroExpanders{};

  if (v >= 9) {
    macroExpanders.push_back(
      cm::make_unique<BaseMacroExpander>(*this, filename));
  }
  macroExpanders.push_back(cm::make_unique<EnvironmentMacroExpander>());

  for (Json::ArrayIndex i = 0; i < presets.Include.size(); ++i) {
    auto include = presets.Include[i];

    // Support for macro expansion in includes added in version 7
    if (v >= 7) {
      if (ExpandMacros(include, macroExpanders, v) != ExpandMacroResult::Ok) {
        cmCMakePresetsErrors::INVALID_INCLUDE(&root["include"][i],
                                              &this->parseState);
        return false;
      }
    }

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

    if ((result = includeFile(include, rootType, ReadReason::Included,
                              errMsg)) != true) {
      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, errMsg)) != true) {
        return result;
      }
    }
  }

  inProgressFiles.pop_back();
  return true;
}
