/* 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 "cmExperimental.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("DESCRIPTION"_s, prArgs.Description)
    .Bind("HOMEPAGE_URL"_s, prArgs.HomepageURL)
    .Bind("LANGUAGES"_s, prArgs.Languages);

  cmMakefile& mf = status.GetMakefile();
  bool enablePackageInfo = cmExperimental::HasSupportEnabled(
    mf, cmExperimental::Feature::ExportPackageInfo);

  if (enablePackageInfo) {
    parser.Bind("COMPAT_VERSION"_s, prArgs.CompatVersion);
    parser.Bind("SPDX_LICENSE"_s, prArgs.License);
  }

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

  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);
  }
}
}
