/* 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 "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.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() ==
          cm::TargetType::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() != cm::TargetType::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() != cm::TargetType::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() != cm::TargetType::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() != cm::TargetType::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() != cm::TargetType::GLOBAL_TARGET) {
    gg->AddTargetAlias(this->GetTargetName(), genTarget, config);
  }
}
