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

#include <algorithm>
#include <array>
#include <iterator>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"

cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
  cmGeneratorTarget* target)
  : cmNinjaTargetGenerator(target)
{
}

cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default;

void cmNinjaUtilityTargetGenerator::Generate(std::string const& config)
{
  if (!this->GetGeneratorTarget()->Target->IsPerConfig()) {
    this->WriteUtilBuildStatements(config, config);
    return;
  }

  for (auto const& fileConfig : this->GetConfigNames()) {
    if (!this->GetGlobalGenerator()
           ->GetCrossConfigs(fileConfig)
           .count(config)) {
      continue;
    }
    if (fileConfig != config &&
        this->GetGeneratorTarget()->GetType() == cmStateEnums::GLOBAL_TARGET) {
      continue;
    }
    this->WriteUtilBuildStatements(config, fileConfig);
  }
}

void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
  std::string const& config, std::string const& fileConfig)
{
  cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
  cmLocalNinjaGenerator* lg = this->GetLocalGenerator();
  cmGeneratorTarget* genTarget = this->GetGeneratorTarget();

  std::string configDir;
  if (genTarget->Target->IsPerConfig()) {
    configDir = gg->ConfigDirectory(fileConfig);
  }
  std::string utilCommandName =
    cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles", configDir, '/',
             this->GetTargetName(), ".util");
  utilCommandName = this->ConvertToNinjaPath(utilCommandName);

  cmNinjaBuild phonyBuild("phony");
  std::vector<std::string> commands;
  cmNinjaDeps deps;
  cmGlobalNinjaGenerator::CCOutputs util_outputs(gg);
  util_outputs.ExplicitOuts.emplace_back(utilCommandName);

  std::string commandDesc;
  cmGeneratorExpression ge(*this->GetLocalGenerator()->GetCMakeInstance());
  bool uses_terminal = false;
  {
    std::array<std::vector<cmCustomCommand> const*, 2> const cmdLists = {
      { &genTarget->GetPreBuildCommands(), &genTarget->GetPostBuildCommands() }
    };

    for (std::vector<cmCustomCommand> const* cmdList : cmdLists) {
      for (cmCustomCommand const& ci : *cmdList) {
        cmCustomCommandGenerator ccg(ci, fileConfig, lg);
        lg->AppendCustomCommandDeps(ccg, deps, fileConfig);
        lg->AppendCustomCommandLines(ccg, commands);
        if (ci.GetComment()) {
          if (!commandDesc.empty()) {
            commandDesc += "; ";
          }
          auto cge = ge.Parse(ci.GetComment());
          commandDesc += cge->Evaluate(this->GetLocalGenerator(), config);
        }
        util_outputs.Add(ccg.GetByproducts());
        if (ci.GetUsesTerminal()) {
          uses_terminal = true;
        }
      }
    }
  }

  {
    std::vector<cmSourceFile*> sources;
    genTarget->GetSourceFiles(sources, config);
    for (cmSourceFile const* source : sources) {
      if (cmCustomCommand const* cc = source->GetCustomCommand()) {
        cmCustomCommandGenerator ccg(*cc, config, lg);
        lg->AddCustomCommandTarget(cc, genTarget);

        // Depend on all custom command outputs.
        std::vector<std::string> const& ccOutputs = ccg.GetOutputs();
        std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
        std::transform(ccOutputs.begin(), ccOutputs.end(),
                       std::back_inserter(deps), this->MapToNinjaPath());
        std::transform(ccByproducts.begin(), ccByproducts.end(),
                       std::back_inserter(deps), this->MapToNinjaPath());
      }
    }
  }

  std::string outputConfig;
  if (genTarget->Target->IsPerConfig()) {
    outputConfig = config;
  }
  lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, outputConfig);
  if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) {
    lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(),
                            config);
    std::copy(util_outputs.ExplicitOuts.begin(),
              util_outputs.ExplicitOuts.end(),
              std::back_inserter(gg->GetByproductsForCleanTarget()));
  }
  lg->AppendTargetDepends(genTarget, deps, config, fileConfig,
                          DependOnTargetArtifact);

  if (commands.empty()) {
    phonyBuild.Comment = "Utility command for " + this->GetTargetName();
    phonyBuild.ExplicitDeps = std::move(deps);
    if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
      gg->WriteBuild(this->GetImplFileStream(fileConfig), phonyBuild);
    } else {
      gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
    }
  } else {
    std::string command = lg->BuildCommandLine(
      commands, config, fileConfig, "utility", this->GeneratorTarget);
    std::string desc;
    cmValue echoStr = genTarget->GetProperty("EchoString");
    if (echoStr) {
      desc = *echoStr;
    } else if (!commandDesc.empty()) {
      desc = commandDesc;
    } else {
      desc = "Running utility command for " + this->GetTargetName();
    }

    // TODO: fix problematic global targets.  For now, search and replace the
    // makefile vars.
    cmSystemTools::ReplaceString(
      command, "$(CMAKE_SOURCE_DIR)",
      lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
                                cmOutputConverter::SHELL));
    cmSystemTools::ReplaceString(
      command, "$(CMAKE_BINARY_DIR)",
      lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
                                cmOutputConverter::SHELL));
    cmSystemTools::ReplaceString(command, "$(ARGS)", "");
    command = gg->ExpandCFGIntDir(command, config);

    std::string ccConfig;
    if (genTarget->Target->IsPerConfig() &&
        genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
      ccConfig = config;
    }
    if (config == fileConfig ||
        gg->GetPerConfigUtilityTargets().count(genTarget->GetName())) {
      gg->WriteCustomCommandBuild(
        command, desc, "Utility command for " + this->GetTargetName(),
        /*depfile*/ "", /*job_pool*/ "", uses_terminal,
        /*restat*/ true, ccConfig, std::move(util_outputs), std::move(deps));
    }

    phonyBuild.ExplicitDeps.push_back(utilCommandName);
    if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
      gg->WriteBuild(this->GetImplFileStream(fileConfig), phonyBuild);
    } else {
      gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
    }
  }

  // Find ADDITIONAL_CLEAN_FILES
  this->AdditionalCleanFiles(config);

  // Add an alias for the logical target name regardless of what directory
  // contains it.  Skip this for GLOBAL_TARGET because they are meant to
  // be per-directory and have one at the top-level anyway.
  if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
    gg->AddTargetAlias(this->GetTargetName(), genTarget, config);
  }
}
