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

#include <sstream>
#include <stdio.h>

#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSystemTools.h"
#include "cmVersion.h"

class cmExecutionStatus;

// cmCMakeMinimumRequired
bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
                                         cmExecutionStatus&)
{
  // Process arguments.
  std::string version_string;
  bool doing_version = false;
  for (std::string const& arg : args) {
    if (arg == "VERSION") {
      doing_version = true;
    } else if (arg == "FATAL_ERROR") {
      if (doing_version) {
        this->SetError("called with no value for VERSION.");
        return false;
      }
      doing_version = false;
    } else if (doing_version) {
      doing_version = false;
      version_string = arg;
    } else {
      this->UnknownArguments.push_back(arg);
    }
  }
  if (doing_version) {
    this->SetError("called with no value for VERSION.");
    return false;
  }

  // Make sure there was a version to check.
  if (version_string.empty()) {
    return this->EnforceUnknownArguments(std::string());
  }

  // Separate the <min> version and any trailing ...<max> component.
  std::string::size_type const dd = version_string.find("...");
  std::string const version_min = version_string.substr(0, dd);
  std::string const version_max = dd != std::string::npos
    ? version_string.substr(dd + 3, std::string::npos)
    : std::string();
  if (dd != std::string::npos &&
      (version_min.empty() || version_max.empty())) {
    std::ostringstream e;
    e << "VERSION \"" << version_string
      << R"(" does not have a version on both sides of "...".)";
    this->SetError(e.str());
    return false;
  }

  // Save the required version string.
  this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
                                version_min.c_str());

  // Get the current version number.
  unsigned int current_major = cmVersion::GetMajorVersion();
  unsigned int current_minor = cmVersion::GetMinorVersion();
  unsigned int current_patch = cmVersion::GetPatchVersion();
  unsigned int current_tweak = cmVersion::GetTweakVersion();

  // Parse at least two components of the version number.
  // Use zero for those not specified.
  unsigned int required_major = 0;
  unsigned int required_minor = 0;
  unsigned int required_patch = 0;
  unsigned int required_tweak = 0;
  if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &required_major,
             &required_minor, &required_patch, &required_tweak) < 2) {
    std::ostringstream e;
    e << "could not parse VERSION \"" << version_min << "\".";
    this->SetError(e.str());
    return false;
  }

  // Compare the version numbers.
  if ((current_major < required_major) ||
      (current_major == required_major && current_minor < required_minor) ||
      (current_major == required_major && current_minor == required_minor &&
       current_patch < required_patch) ||
      (current_major == required_major && current_minor == required_minor &&
       current_patch == required_patch && current_tweak < required_tweak)) {
    // The current version is too low.
    std::ostringstream e;
    e << "CMake " << version_min
      << " or higher is required.  You are running version "
      << cmVersion::GetCMakeVersion();
    this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
    cmSystemTools::SetFatalErrorOccured();
    return true;
  }

  // The version is not from the future, so enforce unknown arguments.
  if (!this->EnforceUnknownArguments(version_max)) {
    return false;
  }

  if (required_major < 2 || (required_major == 2 && required_minor < 4)) {
    this->Makefile->IssueMessage(
      MessageType::AUTHOR_WARNING,
      "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
    this->Makefile->SetPolicyVersion("2.4", version_max);
  } else {
    this->Makefile->SetPolicyVersion(version_min, version_max);
  }

  return true;
}

bool cmCMakeMinimumRequired::EnforceUnknownArguments(
  std::string const& version_max)
{
  if (this->UnknownArguments.empty()) {
    return true;
  }

  // Consider the max version if at least two components were given.
  unsigned int max_major = 0;
  unsigned int max_minor = 0;
  unsigned int max_patch = 0;
  unsigned int max_tweak = 0;
  if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &max_major, &max_minor,
             &max_patch, &max_tweak) >= 2) {
    unsigned int current_major = cmVersion::GetMajorVersion();
    unsigned int current_minor = cmVersion::GetMinorVersion();
    unsigned int current_patch = cmVersion::GetPatchVersion();
    unsigned int current_tweak = cmVersion::GetTweakVersion();

    if ((current_major < max_major) ||
        (current_major == max_major && current_minor < max_minor) ||
        (current_major == max_major && current_minor == max_minor &&
         current_patch < max_patch) ||
        (current_major == max_major && current_minor == max_minor &&
         current_patch == max_patch && current_tweak < max_tweak)) {
      // A ...<max> version was given that is larger than the current
      // version of CMake, so tolerate unknown arguments.
      return true;
    }
  }

  std::ostringstream e;
  e << "called with unknown argument \"" << this->UnknownArguments[0] << "\".";
  this->SetError(e.str());
  return false;
}
