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

#include <array>
#include <cstdio>
#include <limits>
#include <set>
#include <utility>

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

#include "cmsys/RegularExpression.hxx"

#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

namespace {

bool IncludeByVariable(cmExecutionStatus& status, std::string const& variable);
void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name,
                             std::string const& value);

struct ProjectArguments : ArgumentParser::ParseResult
{
  cm::optional<std::string> Version;
  cm::optional<std::string> CompatVersion;
  cm::optional<std::string> License;
  cm::optional<std::string> Description;
  cm::optional<std::string> HomepageURL;
  cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Languages;
};

struct ProjectArgumentParser : public cmArgumentParser<void>
{
  ProjectArgumentParser& BindKeywordMissingValue(
    std::vector<cm::string_view>& ref)
  {
    this->cmArgumentParser<void>::BindKeywordMissingValue(
      [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); });
    return *this;
  }
};

} // namespace

bool cmProjectCommand(std::vector<std::string> const& args,
                      cmExecutionStatus& status)
{
  std::vector<std::string> unparsedArgs;
  std::vector<cm::string_view> missingValueKeywords;
  std::vector<cm::string_view> parsedKeywords;
  ProjectArguments prArgs;
  ProjectArgumentParser parser;
  parser.BindKeywordMissingValue(missingValueKeywords)
    .BindParsedKeywords(parsedKeywords)
    .Bind("VERSION"_s, prArgs.Version)
    .Bind("COMPAT_VERSION"_s, prArgs.CompatVersion)
    .Bind("SPDX_LICENSE"_s, prArgs.License)
    .Bind("DESCRIPTION"_s, prArgs.Description)
    .Bind("HOMEPAGE_URL"_s, prArgs.HomepageURL)
    .Bind("LANGUAGES"_s, prArgs.Languages);

  if (args.empty()) {
    status.SetError("PROJECT called with incorrect number of arguments");
    return false;
  }

  cmMakefile& mf = status.GetMakefile();
  std::string const& projectName = args[0];
  if (parser.HasKeyword(projectName)) {
    mf.IssueMessage(
      MessageType::AUTHOR_WARNING,
      cmStrCat(
        "project() called with '", projectName,
        "' as first argument. The first parameter should be the project name, "
        "not a keyword argument. See the cmake-commands(7) manual for correct "
        "usage of the project() command."));
  }

  parser.Parse(cmMakeRange(args).advance(1), &unparsedArgs, 1);

  if (mf.IsRootMakefile() &&
      !mf.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
    mf.IssueMessage(
      MessageType::AUTHOR_WARNING,
      "cmake_minimum_required() should be called prior to this top-level "
      "project() call. Please see the cmake-commands(7) manual for usage "
      "documentation of both commands.");
  }

  if (!IncludeByVariable(status, "CMAKE_PROJECT_INCLUDE_BEFORE")) {
    return false;
  }

  if (!IncludeByVariable(status,
                         "CMAKE_PROJECT_" + projectName + "_INCLUDE_BEFORE")) {
    return false;
  }

  mf.SetProjectName(projectName);

  cmPolicies::PolicyStatus cmp0180 = mf.GetPolicyStatus(cmPolicies::CMP0180);

  std::string varName = cmStrCat(projectName, "_BINARY_DIR"_s);
  bool nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
  mf.AddCacheDefinition(varName, mf.GetCurrentBinaryDirectory(),
                        "Value Computed by CMake", cmStateEnums::STATIC);
  if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
    mf.AddDefinition(varName, mf.GetCurrentBinaryDirectory());
  }

  varName = cmStrCat(projectName, "_SOURCE_DIR"_s);
  nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
  mf.AddCacheDefinition(varName, mf.GetCurrentSourceDirectory(),
                        "Value Computed by CMake", cmStateEnums::STATIC);
  if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
    mf.AddDefinition(varName, mf.GetCurrentSourceDirectory());
  }

  mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory());
  mf.AddDefinition("PROJECT_SOURCE_DIR", mf.GetCurrentSourceDirectory());

  mf.AddDefinition("PROJECT_NAME", projectName);

  mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile());

  varName = cmStrCat(projectName, "_IS_TOP_LEVEL"_s);
  nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
  mf.AddCacheDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF",
                        "Value Computed by CMake", cmStateEnums::STATIC);
  if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
    mf.AddDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF");
  }

  TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_NAME", projectName);

  std::set<cm::string_view> seenKeywords;
  for (cm::string_view keyword : parsedKeywords) {
    if (seenKeywords.find(keyword) != seenKeywords.end()) {
      mf.IssueMessage(MessageType::FATAL_ERROR,
                      cmStrCat(keyword, " may be specified at most once."));
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
    seenKeywords.insert(keyword);
  }

  for (cm::string_view keyword : missingValueKeywords) {
    mf.IssueMessage(MessageType::WARNING,
                    cmStrCat(keyword,
                             " keyword not followed by a value or was "
                             "followed by a value that expanded to nothing."));
  }

  if (!unparsedArgs.empty()) {
    if (prArgs.Languages) {
      mf.IssueMessage(
        MessageType::WARNING,
        cmStrCat("the following parameters must be specified after LANGUAGES "
                 "keyword: ",
                 cmJoin(unparsedArgs, ", "), '.'));
    } else if (prArgs.Version || prArgs.Description || prArgs.HomepageURL) {
      mf.IssueMessage(MessageType::FATAL_ERROR,
                      "project with VERSION, DESCRIPTION or HOMEPAGE_URL must "
                      "use LANGUAGES before language names.");
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
  } else if (prArgs.Languages && prArgs.Languages->empty()) {
    prArgs.Languages->emplace_back("NONE");
  }

  if (prArgs.CompatVersion && !prArgs.Version) {
    mf.IssueMessage(MessageType::FATAL_ERROR,
                    "project with COMPAT_VERSION must also provide VERSION.");
    cmSystemTools::SetFatalErrorOccurred();
    return true;
  }

  cmsys::RegularExpression vx(
    R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)");

  constexpr std::size_t MAX_VERSION_COMPONENTS = 4u;
  std::string version_string;
  std::array<std::string, MAX_VERSION_COMPONENTS> version_components;

  bool has_version = prArgs.Version.has_value();
  if (prArgs.Version) {
    if (!vx.find(*prArgs.Version)) {
      std::string e =
        R"(VERSION ")" + *prArgs.Version + R"(" format invalid.)";
      mf.IssueMessage(MessageType::FATAL_ERROR, e);
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }

    cmPolicies::PolicyStatus const cmp0096 =
      mf.GetPolicyStatus(cmPolicies::CMP0096);

    if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) {
      constexpr size_t maxIntLength =
        std::numeric_limits<unsigned>::digits10 + 2;
      char vb[MAX_VERSION_COMPONENTS][maxIntLength];
      unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 };
      int const vc = std::sscanf(prArgs.Version->c_str(), "%u.%u.%u.%u", &v[0],
                                 &v[1], &v[2], &v[3]);
      for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) {
        if (static_cast<int>(i) < vc) {
          std::snprintf(vb[i], maxIntLength, "%u", v[i]);
          version_string += &"."[static_cast<std::size_t>(i == 0)];
          version_string += vb[i];
          version_components[i] = vb[i];
        } else {
          vb[i][0] = '\x00';
        }
      }
    } else {
      // The regex above verified that we have a .-separated string of
      // non-negative integer components.  Keep the original string.
      version_string = std::move(*prArgs.Version);
      // Split the integer components.
      auto components = cmSystemTools::SplitString(version_string, '.');
      for (auto i = 0u; i < components.size(); ++i) {
        version_components[i] = std::move(components[i]);
      }
    }
  }

  if (prArgs.CompatVersion) {
    if (!vx.find(*prArgs.CompatVersion)) {
      std::string e =
        R"(COMPAT_VERSION ")" + *prArgs.CompatVersion + R"(" format invalid.)";
      mf.IssueMessage(MessageType::FATAL_ERROR, e);
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }

    if (cmSystemTools::VersionCompareGreater(*prArgs.CompatVersion,
                                             version_string)) {
      mf.IssueMessage(MessageType::FATAL_ERROR,
                      "COMPAT_VERSION must be less than or equal to VERSION");
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
  }

  auto createVariables = [&](cm::string_view var, std::string const& val) {
    mf.AddDefinition(cmStrCat("PROJECT_"_s, var), val);
    mf.AddDefinition(cmStrCat(projectName, "_"_s, var), val);
    TopLevelCMakeVarCondSet(mf, cmStrCat("CMAKE_PROJECT_"_s, var), val);
  };

  // Note, this intentionally doesn't touch cache variables as the legacy
  // behavior did not modify cache
  auto checkAndClearVariables = [&](cm::string_view var) {
    std::vector<std::string> vv = { "PROJECT_", cmStrCat(projectName, '_') };
    if (mf.IsRootMakefile()) {
      vv.push_back("CMAKE_PROJECT_");
    }
    for (std::string const& prefix : vv) {
      std::string def = cmStrCat(prefix, var);
      if (!mf.GetDefinition(def).IsEmpty()) {
        mf.AddDefinition(def, "");
      }
    }
  };

  // TODO: We should treat VERSION the same as all other project variables, but
  // setting it to empty string unconditionally causes various behavior
  // changes. It needs a policy. For now, maintain the old behavior and add a
  // policy in a future release.

  if (has_version) {
    createVariables("VERSION"_s, version_string);
    createVariables("VERSION_MAJOR"_s, version_components[0]);
    createVariables("VERSION_MINOR"_s, version_components[1]);
    createVariables("VERSION_PATCH"_s, version_components[2]);
    createVariables("VERSION_TWEAK"_s, version_components[3]);
  } else {
    checkAndClearVariables("VERSION"_s);
    checkAndClearVariables("VERSION_MAJOR"_s);
    checkAndClearVariables("VERSION_MINOR"_s);
    checkAndClearVariables("VERSION_PATCH"_s);
    checkAndClearVariables("VERSION_TWEAK"_s);
  }

  createVariables("COMPAT_VERSION"_s, prArgs.CompatVersion.value_or(""));
  createVariables("SPDX_LICENSE"_s, prArgs.License.value_or(""));
  createVariables("DESCRIPTION"_s, prArgs.Description.value_or(""));
  createVariables("HOMEPAGE_URL"_s, prArgs.HomepageURL.value_or(""));

  if (unparsedArgs.empty() && !prArgs.Languages) {
    // if no language is specified do c and c++
    mf.EnableLanguage({ "C", "CXX" }, false);
  } else {
    if (!unparsedArgs.empty()) {
      mf.EnableLanguage(unparsedArgs, false);
    }
    if (prArgs.Languages) {
      mf.EnableLanguage(*prArgs.Languages, false);
    }
  }

  if (!IncludeByVariable(status, "CMAKE_PROJECT_INCLUDE")) {
    return false;
  }

  if (!IncludeByVariable(status,
                         "CMAKE_PROJECT_" + projectName + "_INCLUDE")) {
    return false;
  }

  return true;
}

namespace {
bool IncludeByVariable(cmExecutionStatus& status, std::string const& variable)
{
  cmMakefile& mf = status.GetMakefile();
  cmValue include = mf.GetDefinition(variable);
  if (!include) {
    return true;
  }
  cmList includeFiles{ *include };

  bool failed = false;
  for (auto filePath : includeFiles) {
    // Any relative path without a .cmake extension is checked for valid cmake
    // modules. This logic should be consistent with CMake's include() command.
    // Otherwise default to checking relative path w.r.t. source directory
    if (!cmSystemTools::FileIsFullPath(filePath) &&
        !cmHasLiteralSuffix(filePath, ".cmake")) {
      std::string mfile = mf.GetModulesFile(cmStrCat(filePath, ".cmake"));
      if (mfile.empty()) {
        status.SetError(
          cmStrCat("could not find requested module:\n  ", filePath));
        failed = true;
        continue;
      }
      filePath = mfile;
    }
    std::string includeFile = cmSystemTools::CollapseFullPath(
      filePath, mf.GetCurrentSourceDirectory());
    if (!cmSystemTools::FileExists(includeFile)) {
      status.SetError(
        cmStrCat("could not find requested file:\n  ", filePath));
      failed = true;
      continue;
    }
    if (cmSystemTools::FileIsDirectory(includeFile)) {
      status.SetError(
        cmStrCat("requested file is a directory:\n  ", filePath));
      failed = true;
      continue;
    }

    bool const readit = mf.ReadDependentFile(filePath);
    if (readit) {
      // If the included file ran successfully, continue to the next file
      continue;
    }

    if (cmSystemTools::GetFatalErrorOccurred()) {
      failed = true;
      continue;
    }

    status.SetError(cmStrCat("could not load requested file:\n  ", filePath));
    failed = true;
  }
  // At this point all files were processed
  return !failed;
}

void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name,
                             std::string const& value)
{
  // Set the CMAKE_PROJECT_XXX variable to be the highest-level
  // project name in the tree. If there are two project commands
  // in the same CMakeLists.txt file, and it is the top level
  // CMakeLists.txt file, then go with the last one.
  if (!mf.GetDefinition(name) || mf.IsRootMakefile()) {
    mf.RemoveDefinition(name);
    mf.AddCacheDefinition(name, value, "Value Computed by CMake",
                          cmStateEnums::STATIC);
  }
}
}
