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

#include "cmFastbuildUtilityTargetGenerator.h"

#include <set>
#include <string>
#include <utility>
#include <vector>

#include <cm/memory>

#include "cmFastbuildTargetGenerator.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalFastbuildGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmTargetTypes.h"

cmFastbuildUtilityTargetGenerator::cmFastbuildUtilityTargetGenerator(
  cmGeneratorTarget* gt, std::string configParam)
  : cmFastbuildTargetGenerator(gt, std::move(configParam))
{
}

void cmFastbuildUtilityTargetGenerator::Generate()
{
  if (!this->GetGeneratorTarget()->IsInBuildSystem()) {
    return;
  }
  std::string targetName = GeneratorTarget->GetName();

  if (this->GeneratorTarget->GetType() == cm::TargetType::GLOBAL_TARGET) {
    targetName = GetGlobalGenerator()->GetTargetName(GeneratorTarget);
  }

  FastbuildAliasNode fastbuildTarget;
  auto const addUtilDepToTarget = [&fastbuildTarget](std::string depName) {
    FastbuildTargetDep dep{ depName };
    dep.Type = FastbuildTargetDepType::UTIL;
    fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
  };

  fastbuildTarget.Name = targetName;
  fastbuildTarget.BaseName = targetName;

  LogMessage("<-------------->");
  LogMessage("Generate Utility target: " + targetName);
  LogMessage("Config: " + Config);
  for (auto const& dep : TargetDirectDependencies) {
    LogMessage("Dep: " + dep->GetName());
  }

  std::vector<std::string> nonImportedUtils;
  for (BT<std::pair<std::string, bool>> const& util :
       this->GeneratorTarget->GetUtilities()) {
    if (util.Value.first == targetName) {
      continue;
    }
    auto const& utilTargetName =
      this->ConvertToFastbuildPath(util.Value.first);
    LogMessage("Util: " + utilTargetName);
    auto* const target = this->Makefile->FindTargetToUse(utilTargetName);
    if (target && target->IsImported()) {
      LogMessage("Skipping imported util target: " + utilTargetName);
      continue;
    }
    // Since interface target don't appear in the generated build files,
    // transitively propagate their deps (if any).
    // Tested in "ExternalProjectSubdir" test.
    if (target && target->GetType() == cm::TargetType::INTERFACE_LIBRARY) {
      for (auto const& dep : target->GetUtilities()) {
        auto const& depName = this->ConvertToFastbuildPath(dep.Value.first);
        LogMessage(cmStrCat("Transitively propagating iface dep: ", depName,
                            ", is cross: ", std::to_string(dep.Value.second)));
        nonImportedUtils.emplace_back(depName);
        addUtilDepToTarget(this->ConvertToFastbuildPath(depName));
      }
    } else {
      nonImportedUtils.emplace_back(utilTargetName);
      addUtilDepToTarget(utilTargetName);
    }
  }
  if (this->GetGlobalGenerator()->IsExcluded(this->GetGeneratorTarget())) {
    LogMessage(cmStrCat("Excluding ", targetName, " from ALL"));
    fastbuildTarget.ExcludeFromAll = true;
  }
  auto preBuild = GenerateCommands(FastbuildBuildStep::PRE_BUILD);

  // Tested in "RunCMake.CPack*" tests.
  // Utility target "package" has packaging steps as "POST_BUILD".
  for (auto& exec : GenerateCommands(FastbuildBuildStep::POST_BUILD).Nodes) {
    addUtilDepToTarget(exec.Name);
    for (std::string const& util : nonImportedUtils) {
      LogMessage("Adding: util " + util);
      exec.PreBuildDependencies.emplace(util);
    }
    // So POST_BUILD is executed AFTER PRE_BUILD (tested in "CustomCommand"
    // test).
    for (auto const& pre : preBuild.Nodes) {
      LogMessage("Adding: " + pre.Name);
      exec.PreBuildDependencies.emplace(pre.Name);
    }
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
  }

  for (auto& exec : preBuild.Nodes) {
    LogMessage("Adding exec " + exec.Name);
    addUtilDepToTarget(exec.Name);
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
  }

  for (auto& exec : GenerateCommands(FastbuildBuildStep::REST).Nodes) {
    addUtilDepToTarget(exec.Name);
    for (auto const& dep : TargetDirectDependencies) {
      LogMessage(cmStrCat("Direct dep ", dep->GetName(),
                          "-all propagating to CC: ", exec.Name));
      // All custom commands from within the target must be executed AFTER all
      // the target's deps.
      exec.PreBuildDependencies.emplace(dep->GetName());
    }
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
  }
  // The target has to be in the build system, but has no custom commands
  // associated with it.
  if (fastbuildTarget.PreBuildDependencies.empty()) {
    std::vector<cmSourceFile*> sources;
    this->GetGeneratorTarget()->GetSourceFiles(sources, this->Config);
    if (sources.empty()) {
      FastbuildTargetDep dep{ FASTBUILD_NOOP_FILE_NAME };
      dep.Type = FastbuildTargetDepType::ORDER_ONLY;
      fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
    } else {
      for (cmSourceFile const* source : sources) {
        FastbuildTargetDep dep{
          this->GetGlobalGenerator()->ConvertToFastbuildPath(
            source->GetFullPath())
        };
        dep.Type = FastbuildTargetDepType::ARTIFACT;
        fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
      }
    }
  }

  fastbuildTarget.Hidden = false;
  this->AdditionalCleanFiles();

  fastbuildTarget.BasePath = this->GetMakefile()->GetCurrentSourceDirectory();
  if (this->GetGeneratorTarget()->GetType() != cm::TargetType::GLOBAL_TARGET) {
    this->GetGlobalGenerator()->AddIDEProject(fastbuildTarget, Config);
  }
  this->GetGlobalGenerator()->AddTarget(std::move(fastbuildTarget));
}
