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

#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

namespace {

bool MainSignature(std::vector<std::string> const& args,
                   cmExecutionStatus& status)
{
  if (args.empty()) {
    status.SetError("requires at least one argument naming a CMake variable");
    return false;
  }

  // The cmake variable in which to store the result.
  std::string const& variable = args[0];

  // Parse remaining arguments.
  std::string configuration;
  std::string project_name;
  std::string target;
  std::string parallel;
  enum Doing
  {
    DoingNone,
    DoingConfiguration,
    DoingProjectName,
    DoingTarget,
    DoingParallel
  };
  Doing doing = DoingNone;
  for (unsigned int i = 1; i < args.size(); ++i) {
    if (args[i] == "CONFIGURATION") {
      doing = DoingConfiguration;
    } else if (args[i] == "PROJECT_NAME") {
      doing = DoingProjectName;
    } else if (args[i] == "TARGET") {
      doing = DoingTarget;
    } else if (args[i] == "PARALLEL_LEVEL") {
      doing = DoingParallel;
    } else if (doing == DoingConfiguration) {
      doing = DoingNone;
      configuration = args[i];
    } else if (doing == DoingProjectName) {
      doing = DoingNone;
      project_name = args[i];
    } else if (doing == DoingTarget) {
      doing = DoingNone;
      target = args[i];
    } else if (doing == DoingParallel) {
      doing = DoingNone;
      parallel = args[i];
    } else {
      status.SetError(cmStrCat("unknown argument \"", args[i], '"'));
      return false;
    }
  }

  // If null/empty CONFIGURATION argument, cmake --build uses 'Debug'
  // in the currently implemented multi-configuration global generators...
  // so we put this code here to end up with the same default configuration
  // as the original 2-arg build_command signature:
  //
  if (configuration.empty()) {
    cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configuration);
  }
  if (configuration.empty()) {
    configuration = "Release";
  }

  cmMakefile& mf = status.GetMakefile();
  if (!project_name.empty()) {
    mf.IssueMessage(MessageType::AUTHOR_WARNING,
                    "Ignoring PROJECT_NAME option because it has no effect.");
  }

  std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand(
    target, configuration, parallel, "", false);

  mf.AddDefinition(variable, makecommand);

  return true;
}

bool TwoArgsSignature(std::vector<std::string> const& args,
                      cmExecutionStatus& status)
{
  if (args.size() < 2) {
    status.SetError("called with less than two arguments");
    return false;
  }

  cmMakefile& mf = status.GetMakefile();

  std::string const& define = args[0];
  cmValue cacheValue = mf.GetDefinition(define);

  std::string configType;
  if (!cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType) ||
      configType.empty()) {
    configType = "Release";
  }

  std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand(
    "", configType, "", "", false);

  if (cacheValue) {
    return true;
  }
  mf.AddCacheDefinition(define, makecommand,
                        "Command used to build entire project "
                        "from the command line.",
                        cmStateEnums::STRING);
  return true;
}

} // namespace

bool cmBuildCommand(std::vector<std::string> const& args,
                    cmExecutionStatus& status)
{
  // Support the legacy signature of the command:
  if (args.size() == 2) {
    return TwoArgsSignature(args, status);
  }

  return MainSignature(args, status);
}
