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

#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetTypes.h"

bool cmAddExecutableCommand(std::vector<std::string> const& args,
                            cmExecutionStatus& status)
{
  if (args.empty()) {
    status.SetError("called with incorrect number of arguments");
    return false;
  }

  cmMakefile& mf = status.GetMakefile();
  auto s = args.begin();

  std::string const& exename = *s;

  ++s;
  bool use_win32 = false;
  bool use_macbundle = false;
  bool excludeFromAll = false;
  bool importTarget = false;
  bool importGlobal = false;
  bool isAlias = false;
  while (s != args.end()) {
    if (*s == "WIN32") {
      ++s;
      use_win32 = true;
    } else if (*s == "MACOSX_BUNDLE") {
      ++s;
      use_macbundle = true;
    } else if (*s == "EXCLUDE_FROM_ALL") {
      ++s;
      excludeFromAll = true;
    } else if (*s == "IMPORTED") {
      ++s;
      importTarget = true;
    } else if (importTarget && *s == "GLOBAL") {
      ++s;
      importGlobal = true;
    } else if (*s == "ALIAS") {
      ++s;
      isAlias = true;
    } else {
      break;
    }
  }

  if (importTarget && !importGlobal) {
    importGlobal = mf.IsImportedTargetGlobalScope();
  }

  bool nameOk = cmGeneratorExpression::IsValidTargetName(exename) &&
    !cmGlobalGenerator::IsReservedTarget(exename);

  if (nameOk && !importTarget && !isAlias) {
    nameOk = exename.find(':') == std::string::npos;
  }
  if (!nameOk) {
    mf.IssueInvalidTargetNameError(exename);
    return false;
  }

  // Special modifiers are not allowed with IMPORTED signature.
  if (importTarget && (use_win32 || use_macbundle || excludeFromAll)) {
    if (use_win32) {
      status.SetError("may not be given WIN32 for an IMPORTED target.");
    } else if (use_macbundle) {
      status.SetError(
        "may not be given MACOSX_BUNDLE for an IMPORTED target.");
    } else // if(excludeFromAll)
    {
      status.SetError(
        "may not be given EXCLUDE_FROM_ALL for an IMPORTED target.");
    }
    return false;
  }
  if (isAlias) {
    if (!cmGeneratorExpression::IsValidTargetName(exename)) {
      status.SetError("Invalid name for ALIAS: " + exename);
      return false;
    }
    if (excludeFromAll) {
      status.SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
      return false;
    }
    if (importTarget || importGlobal) {
      status.SetError("IMPORTED with ALIAS is not allowed.");
      return false;
    }
    if (args.size() != 3) {
      status.SetError("ALIAS requires exactly one target argument.");
      return false;
    }

    std::string const& aliasedName = *s;
    if (mf.IsAlias(aliasedName)) {
      status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
                               "\" because target \"", aliasedName,
                               "\" is itself an ALIAS."));
      return false;
    }
    cmTarget* aliasedTarget =
      mf.FindTargetToUse(aliasedName, { cm::TargetDomain::NATIVE });
    if (!aliasedTarget) {
      status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
                               "\" because target \"", aliasedName,
                               "\" does not already exist."));
      return false;
    }
    cm::TargetType type = aliasedTarget->GetType();
    if (type != cm::TargetType::EXECUTABLE) {
      status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
                               "\" because target \"", aliasedName,
                               "\" is not an executable."));
      return false;
    }
    mf.AddAlias(exename, aliasedName,
                !aliasedTarget->IsImported() ||
                  aliasedTarget->IsImportedGloballyVisible());
    return true;
  }

  // Handle imported target creation.
  if (importTarget) {
    // Make sure the target does not already exist.
    if (mf.FindTargetToUse(exename)) {
      status.SetError(cmStrCat(
        "cannot create imported target \"", exename,
        "\" because another target with the same name already exists."));
      return false;
    }

    // Create the imported target.
    mf.AddImportedTarget(exename, cm::TargetType::EXECUTABLE,
                         importGlobal ? cm::ImportedTargetScope::Global
                                      : cm::ImportedTargetScope::Local);
    return true;
  }

  // Enforce name uniqueness.
  {
    std::string msg;
    if (!mf.EnforceUniqueName(exename, msg)) {
      status.SetError(msg);
      return false;
    }
  }

  std::vector<std::string> srclists(s, args.end());
  cmTarget* tgt = mf.AddExecutable(exename, srclists, excludeFromAll);
  if (use_win32) {
    tgt->SetProperty("WIN32_EXECUTABLE", "ON");
  }
  if (use_macbundle) {
    tgt->SetProperty("MACOSX_BUNDLE", "ON");
  }

  return true;
}
