#include "cmPolicies.h"

#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <vector>

#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"

static bool stringToId(const char* input, cmPolicies::PolicyID& pid)
{
  assert(input);
  if (strlen(input) != 7) {
    return false;
  }
  if (!cmHasLiteralPrefix(input, "CMP")) {
    return false;
  }
  if (cmHasLiteralSuffix(input, "0000")) {
    pid = cmPolicies::CMP0000;
    return true;
  }
  for (int i = 3; i < 7; ++i) {
    if (!isdigit(*(input + i))) {
      return false;
    }
  }
  long id;
  if (!cmStrToLong(input + 3, &id)) {
    return false;
  }
  if (id >= cmPolicies::CMPCOUNT) {
    return false;
  }
  pid = cmPolicies::PolicyID(id);
  return true;
}

#define CM_SELECT_ID_VERSION(F, A1, A2, A3, A4, A5, A6) F(A1, A3, A4, A5)
#define CM_FOR_EACH_POLICY_ID_VERSION(POLICY)                                 \
  CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID_VERSION)

#define CM_SELECT_ID_DOC(F, A1, A2, A3, A4, A5, A6) F(A1, A2)
#define CM_FOR_EACH_POLICY_ID_DOC(POLICY)                                     \
  CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID_DOC)

static const char* idToString(cmPolicies::PolicyID id)
{
  switch (id) {
#define POLICY_CASE(ID)                                                       \
  case cmPolicies::ID:                                                        \
    return #ID;
    CM_FOR_EACH_POLICY_ID(POLICY_CASE)
#undef POLICY_CASE
    case cmPolicies::CMPCOUNT:
      return nullptr;
  }
  return nullptr;
}

static const char* idToVersion(cmPolicies::PolicyID id)
{
  switch (id) {
#define POLICY_CASE(ID, V_MAJOR, V_MINOR, V_PATCH)                            \
  case cmPolicies::ID:                                                        \
    return #V_MAJOR "." #V_MINOR "." #V_PATCH;
    // NOLINTNEXTLINE(bugprone-branch-clone)
    CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE)
#undef POLICY_CASE
    case cmPolicies::CMPCOUNT:
      return nullptr;
  }
  return nullptr;
}

static bool isPolicyNewerThan(cmPolicies::PolicyID id, unsigned int majorV,
                              unsigned int minorV, unsigned int patchV)
{
  switch (id) {
#define POLICY_CASE(ID, V_MAJOR, V_MINOR, V_PATCH)                            \
  case cmPolicies::ID:                                                        \
    return (majorV < (V_MAJOR) ||                                             \
            (majorV == (V_MAJOR) && minorV + 1 < (V_MINOR) + 1) ||            \
            (majorV == (V_MAJOR) && minorV == (V_MINOR) &&                    \
             patchV + 1 < (V_PATCH) + 1));
    // NOLINTNEXTLINE(bugprone-branch-clone)
    CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE)
#undef POLICY_CASE
    case cmPolicies::CMPCOUNT:
      return false;
  }
  return false;
}

const char* idToShortDescription(cmPolicies::PolicyID id)
{
  switch (id) {
#define POLICY_CASE(ID, SHORT_DESCRIPTION)                                    \
  case cmPolicies::ID:                                                        \
    return SHORT_DESCRIPTION;
    CM_FOR_EACH_POLICY_ID_DOC(POLICY_CASE)
#undef POLICY_CASE
    case cmPolicies::CMPCOUNT:
      return nullptr;
  }
  return nullptr;
}

static void DiagnoseAncientPolicies(
  std::vector<cmPolicies::PolicyID> const& ancient, unsigned int majorVer,
  unsigned int minorVer, unsigned int patchVer, cmMakefile* mf)
{
  std::ostringstream e;
  e << "The project requests behavior compatible with CMake version \""
    << majorVer << "." << minorVer << "." << patchVer
    << "\", which requires the OLD behavior for some policies:\n";
  for (cmPolicies::PolicyID i : ancient) {
    e << "  " << idToString(i) << ": " << idToShortDescription(i) << "\n";
  }
  e << "However, this version of CMake no longer supports the OLD "
    << "behavior for these policies.  "
    << "Please either update your CMakeLists.txt files to conform to "
    << "the new behavior or use an older version of CMake that still "
    << "supports the old behavior.";
  mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
}

static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
                             cmPolicies::PolicyStatus* defaultSetting)
{
  std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy;
  std::string const& defaultValue = mf->GetSafeDefinition(defaultVar);
  if (defaultValue == "NEW") {
    *defaultSetting = cmPolicies::NEW;
  } else if (defaultValue == "OLD") {
    *defaultSetting = cmPolicies::OLD;
  } else if (defaultValue.empty()) {
    *defaultSetting = cmPolicies::WARN;
  } else {
    std::ostringstream e;
    e << defaultVar << " has value \"" << defaultValue
      << R"(" but must be "OLD", "NEW", or "" (empty).)";
    mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
    return false;
  }

  return true;
}

bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
                                    std::string const& version_min,
                                    std::string const& version_max,
                                    WarnCompat warnCompat)
{
  // Parse components of the minimum version.
  unsigned int minMajor = 2;
  unsigned int minMinor = 0;
  unsigned int minPatch = 0;
  unsigned int minTweak = 0;
  if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &minMajor, &minMinor,
             &minPatch, &minTweak) < 2) {
    std::ostringstream e;
    e << "Invalid policy version value \"" << version_min << "\".  "
      << "A numeric major.minor[.patch[.tweak]] must be given.";
    mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
    return false;
  }

  // it is an error if the policy version is less than 2.4
  if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) {
    mf->IssueMessage(
      MessageType::FATAL_ERROR,
      "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.  "
      "For compatibility with older versions please use any CMake 2.8.x "
      "release or lower.");
    return false;
  }

  // It is an error if the policy version is greater than the running
  // CMake.
  if (minMajor > cmVersion::GetMajorVersion() ||
      (minMajor == cmVersion::GetMajorVersion() &&
       minMinor > cmVersion::GetMinorVersion()) ||
      (minMajor == cmVersion::GetMajorVersion() &&
       minMinor == cmVersion::GetMinorVersion() &&
       minPatch > cmVersion::GetPatchVersion()) ||
      (minMajor == cmVersion::GetMajorVersion() &&
       minMinor == cmVersion::GetMinorVersion() &&
       minPatch == cmVersion::GetPatchVersion() &&
       minTweak > cmVersion::GetTweakVersion())) {
    std::ostringstream e;
    e << "An attempt was made to set the policy version of CMake to \""
      << version_min << "\" which is greater than this version of CMake.  "
      << "This is not allowed because the greater version may have new "
      << "policies not known to this CMake.  "
      << "You may need a newer CMake version to build this project.";
    mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
    return false;
  }

  unsigned int polMajor = minMajor;
  unsigned int polMinor = minMinor;
  unsigned int polPatch = minPatch;

  if (!version_max.empty()) {
    // Parse components of the maximum version.
    unsigned int maxMajor = 0;
    unsigned int maxMinor = 0;
    unsigned int maxPatch = 0;
    unsigned int maxTweak = 0;
    if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &maxMajor, &maxMinor,
               &maxPatch, &maxTweak) < 2) {
      std::ostringstream e;
      e << "Invalid policy max version value \"" << version_max << "\".  "
        << "A numeric major.minor[.patch[.tweak]] must be given.";
      mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return false;
    }

    // It is an error if the min version is greater than the max version.
    if (minMajor > maxMajor || (minMajor == maxMajor && minMinor > maxMinor) ||
        (minMajor == maxMajor && minMinor == maxMinor &&
         minPatch > maxPatch) ||
        (minMajor == maxMajor && minMinor == maxMinor &&
         minPatch == maxPatch && minTweak > maxTweak)) {
      std::ostringstream e;
      e << "Policy VERSION range \"" << version_min << "..." << version_max
        << "\""
        << " specifies a larger minimum than maximum.";
      mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return false;
    }

    // Use the max version as the policy version.
    polMajor = maxMajor;
    polMinor = maxMinor;
    polPatch = maxPatch;
  }

  return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch,
                                        warnCompat);
}

bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
                                    unsigned int minorVer,
                                    unsigned int patchVer,
                                    WarnCompat warnCompat)
{
  // Warn about policy versions for which support will be removed.
  if (warnCompat == WarnCompat::On &&
      (majorVer < 2 || (majorVer == 2 && minorVer < 8) ||
       (majorVer == 2 && minorVer == 8 && patchVer < 12)) &&
      // Avoid warning on calls generated by install(EXPORT)
      // in CMake versions prior to 3.18.
      !(majorVer == 2 && minorVer == 6 && patchVer == 0 &&
        mf->GetStateSnapshot().CanPopPolicyScope() &&
        cmSystemTools::Strucmp(mf->GetBacktrace().Top().Name.c_str(),
                               "cmake_policy") == 0)) {
    mf->IssueMessage(
      MessageType::DEPRECATION_WARNING,
      "Compatibility with CMake < 2.8.12 will be removed from "
      "a future version of CMake.\n"
      "Update the VERSION argument <min> value or use a ...<max> suffix "
      "to tell CMake that the project does not need compatibility with "
      "older versions.");
  }

  // now loop over all the policies and set them as appropriate
  std::vector<cmPolicies::PolicyID> ancientPolicies;
  for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
       pid = PolicyID(pid + 1)) {
    if (isPolicyNewerThan(pid, majorVer, minorVer, patchVer)) {
      if (cmPolicies::GetPolicyStatus(pid) == cmPolicies::REQUIRED_ALWAYS) {
        ancientPolicies.push_back(pid);
      } else {
        cmPolicies::PolicyStatus status = cmPolicies::WARN;
        if (!GetPolicyDefault(mf, idToString(pid), &status) ||
            !mf->SetPolicy(pid, status)) {
          return false;
        }
        if (pid == cmPolicies::CMP0001 &&
            (status == cmPolicies::WARN || status == cmPolicies::OLD)) {
          if (!(mf->GetState()->GetInitializedCacheValue(
                "CMAKE_BACKWARDS_COMPATIBILITY"))) {
            // Set it to 2.4 because that is the last version where the
            // variable had meaning.
            mf->AddCacheDefinition(
              "CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
              "For backwards compatibility, what version of CMake "
              "commands and "
              "syntax should this version of CMake try to support.",
              cmStateEnums::STRING);
          }
        }
      }
    } else {
      if (!mf->SetPolicy(pid, cmPolicies::NEW)) {
        return false;
      }
    }
  }

  // Make sure the project does not use any ancient policies.
  if (!ancientPolicies.empty()) {
    DiagnoseAncientPolicies(ancientPolicies, majorVer, minorVer, patchVer, mf);
    cmSystemTools::SetFatalErrorOccured();
    return false;
  }

  return true;
}

bool cmPolicies::GetPolicyID(const char* id, cmPolicies::PolicyID& pid)
{
  return stringToId(id, pid);
}

//! return a warning string for a given policy
std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
{
  std::ostringstream msg;
  msg << "Policy " << idToString(id)
      << " is not set: "
         ""
      << idToShortDescription(id)
      << "  "
         "Run \"cmake --help-policy "
      << idToString(id)
      << "\" for "
         "policy details.  "
         "Use the cmake_policy command to set the policy "
         "and suppress this warning.";
  return msg.str();
}

std::string cmPolicies::GetPolicyDeprecatedWarning(cmPolicies::PolicyID id)
{
  std::ostringstream msg;
  /* clang-format off */
  msg <<
    "The OLD behavior for policy " << idToString(id) << " "
    "will be removed from a future version of CMake.\n"
    "The cmake-policies(7) manual explains that the OLD behaviors of all "
    "policies are deprecated and that a policy should be set to OLD only "
    "under specific short-term circumstances.  Projects should be ported "
    "to the NEW behavior and not rely on setting a policy to OLD."
    ;
  /* clang-format on */
  return msg.str();
}

//! return an error string for when a required policy is unspecified
std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
{
  std::ostringstream error;
  error << "Policy " << idToString(id)
        << " is not set to NEW: "
           ""
        << idToShortDescription(id)
        << "  "
           "Run \"cmake --help-policy "
        << idToString(id)
        << "\" for "
           "policy details.  "
           "CMake now requires this policy to be set to NEW by the project.  "
           "The policy may be set explicitly using the code\n"
           "  cmake_policy(SET "
        << idToString(id)
        << " NEW)\n"
           "or by upgrading all policies with the code\n"
           "  cmake_policy(VERSION "
        << idToVersion(id)
        << ") # or later\n"
           "Run \"cmake --help-command cmake_policy\" for more information.";
  return error.str();
}

//! Get the default status for a policy
cmPolicies::PolicyStatus cmPolicies::GetPolicyStatus(
  cmPolicies::PolicyID /*unused*/)
{
  return cmPolicies::WARN;
}

std::string cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id)
{
  std::string pid = idToString(id);
  std::ostringstream e;
  e << "Policy " << pid << " may not be set to OLD behavior because this "
    << "version of CMake no longer supports it.  "
    << "The policy was introduced in "
    << "CMake version " << idToVersion(id)
    << ", and use of NEW behavior is now required."
    << "\n"
    << "Please either update your CMakeLists.txt files to conform to "
    << "the new behavior or use an older version of CMake that still "
    << "supports the old behavior.  "
    << "Run cmake --help-policy " << pid << " for more information.";
  return e.str();
}

cmPolicies::PolicyStatus cmPolicies::PolicyMap::Get(
  cmPolicies::PolicyID id) const
{
  PolicyStatus status = cmPolicies::WARN;

  if (this->Status[(POLICY_STATUS_COUNT * id) + OLD]) {
    status = cmPolicies::OLD;
  } else if (this->Status[(POLICY_STATUS_COUNT * id) + NEW]) {
    status = cmPolicies::NEW;
  }
  return status;
}

void cmPolicies::PolicyMap::Set(cmPolicies::PolicyID id,
                                cmPolicies::PolicyStatus status)
{
  this->Status[(POLICY_STATUS_COUNT * id) + OLD] = (status == OLD);
  this->Status[(POLICY_STATUS_COUNT * id) + WARN] = (status == WARN);
  this->Status[(POLICY_STATUS_COUNT * id) + NEW] = (status == NEW);
}

bool cmPolicies::PolicyMap::IsDefined(cmPolicies::PolicyID id) const
{
  return this->Status[(POLICY_STATUS_COUNT * id) + OLD] ||
    this->Status[(POLICY_STATUS_COUNT * id) + WARN] ||
    this->Status[(POLICY_STATUS_COUNT * id) + NEW];
}

bool cmPolicies::PolicyMap::IsEmpty() const
{
  return this->Status.none();
}
