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

#include <utility>

#include <cm/memory>

#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"

bool cmAddCustomTargetCommand(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();
  std::string const& targetName = args[0];

  // Check the target name.
  if (targetName.find_first_of("/\\") != std::string::npos) {
    status.SetError(cmStrCat("called with invalid target name \"", targetName,
                             "\".  Target names may not contain a slash.  "
                             "Use ADD_CUSTOM_COMMAND to generate files."));
    return false;
  }

  // Accumulate one command line at a time.
  cmCustomCommandLine currentLine;

  // Save all command lines.
  cmCustomCommandLines commandLines;

  // Accumulate dependencies.
  std::vector<std::string> depends;
  std::vector<std::string> byproducts;
  std::string working_directory;
  bool verbatim = false;
  bool uses_terminal = false;
  bool command_expand_lists = false;
  std::string comment_buffer;
  char const* comment = nullptr;
  std::vector<std::string> sources;
  std::string job_pool;
  std::string job_server_aware;

  // Keep track of parser state.
  enum tdoing
  {
    doing_command,
    doing_depends,
    doing_byproducts,
    doing_working_directory,
    doing_comment,
    doing_source,
    doing_job_pool,
    doing_job_server_aware,
    doing_nothing
  };
  tdoing doing = doing_command;

  // Look for the ALL option.
  bool excludeFromAll = true;
  unsigned int start = 1;
  if (args.size() > 1) {
    if (args[1] == "ALL") {
      excludeFromAll = false;
      start = 2;
    }
  }

  // Parse the rest of the arguments.
  for (unsigned int j = start; j < args.size(); ++j) {
    std::string const& copy = args[j];

    if (copy == "DEPENDS") {
      doing = doing_depends;
    } else if (copy == "BYPRODUCTS") {
      doing = doing_byproducts;
    } else if (copy == "WORKING_DIRECTORY") {
      doing = doing_working_directory;
    } else if (copy == "VERBATIM") {
      doing = doing_nothing;
      verbatim = true;
    } else if (copy == "USES_TERMINAL") {
      doing = doing_nothing;
      uses_terminal = true;
    } else if (copy == "COMMAND_EXPAND_LISTS") {
      doing = doing_nothing;
      command_expand_lists = true;
    } else if (copy == "COMMENT") {
      doing = doing_comment;
    } else if (copy == "JOB_POOL") {
      doing = doing_job_pool;
    } else if (copy == "JOB_SERVER_AWARE") {
      doing = doing_job_server_aware;
    } else if (copy == "COMMAND") {
      doing = doing_command;

      // Save the current command before starting the next command.
      if (!currentLine.empty()) {
        commandLines.push_back(currentLine);
        currentLine.clear();
      }
    } else if (copy == "SOURCES") {
      doing = doing_source;
    } else {
      switch (doing) {
        case doing_working_directory:
          working_directory = copy;
          break;
        case doing_command:
          currentLine.push_back(copy);
          break;
        case doing_byproducts: {
          std::string filename;
          if (!cmSystemTools::FileIsFullPath(copy) &&
              cmGeneratorExpression::Find(copy) != 0) {
            filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
          }
          filename += copy;
          cmSystemTools::ConvertToUnixSlashes(filename);
          if (cmSystemTools::FileIsFullPath(filename)) {
            filename = cmSystemTools::CollapseFullPath(filename);
          }
          byproducts.push_back(filename);
        } break;
        case doing_depends: {
          std::string dep = copy;
          cmSystemTools::ConvertToUnixSlashes(dep);
          depends.push_back(std::move(dep));
        } break;
        case doing_comment:
          comment_buffer = copy;
          comment = comment_buffer.c_str();
          break;
        case doing_source:
          sources.push_back(copy);
          break;
        case doing_job_pool:
          job_pool = copy;
          break;
        case doing_job_server_aware:
          job_server_aware = copy;
          break;
        default:
          status.SetError("Wrong syntax. Unknown type of argument.");
          return false;
      }
    }
  }

  bool nameOk = cmGeneratorExpression::IsValidTargetName(targetName) &&
    !cmGlobalGenerator::IsReservedTarget(targetName) &&
    targetName.find(':') == std::string::npos;
  if (!nameOk) {
    mf.IssueInvalidTargetNameError(targetName);
    return false;
  }

  // Store the last command line finished.
  if (!currentLine.empty()) {
    commandLines.push_back(currentLine);
    currentLine.clear();
  }

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

  if (commandLines.empty() && !byproducts.empty()) {
    mf.IssueMessage(MessageType::FATAL_ERROR,
                    "BYPRODUCTS may not be specified without any COMMAND");
    return true;
  }
  if (commandLines.empty() && uses_terminal) {
    mf.IssueMessage(MessageType::FATAL_ERROR,
                    "USES_TERMINAL may not be specified without any COMMAND");
    return true;
  }
  if (commandLines.empty() && command_expand_lists) {
    mf.IssueMessage(
      MessageType::FATAL_ERROR,
      "COMMAND_EXPAND_LISTS may not be specified without any COMMAND");
    return true;
  }

  if (uses_terminal && !job_pool.empty()) {
    status.SetError("JOB_POOL is shadowed by USES_TERMINAL.");
    return false;
  }

  // Add the utility target to the makefile.
  auto cc = cm::make_unique<cmCustomCommand>();
  cc->SetWorkingDirectory(working_directory.c_str());
  cc->SetByproducts(byproducts);
  cc->SetDepends(depends);
  cc->SetCommandLines(commandLines);
  cc->SetEscapeOldStyle(!verbatim);
  cc->SetComment(comment);
  cc->SetUsesTerminal(uses_terminal);
  cc->SetCommandExpandLists(command_expand_lists);
  cc->SetJobPool(job_pool);
  cc->SetJobserverAware(cmIsOn(job_server_aware));
  cmTarget* target =
    mf.AddUtilityCommand(targetName, excludeFromAll, std::move(cc));

  // Add additional user-specified source files to the target.
  target->AddSources(sources);

  return true;
}
