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

#include <set>
#include <utility>

#include <cm/memory>

#include "cmCustomCommand.h"
#include "cmDiagnostics.h"
#include "cmDuration.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenInitializer.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"

cmQtAutoGenGlobalInitializer::Keywords::Keywords()
  : AUTOMOC("AUTOMOC")
  , AUTOUIC("AUTOUIC")
  , AUTORCC("AUTORCC")
  , AUTOMOC_EXECUTABLE("AUTOMOC_EXECUTABLE")
  , AUTOUIC_EXECUTABLE("AUTOUIC_EXECUTABLE")
  , AUTORCC_EXECUTABLE("AUTORCC_EXECUTABLE")
  , SKIP_AUTOGEN("SKIP_AUTOGEN")
  , SKIP_AUTOMOC("SKIP_AUTOMOC")
  , SKIP_AUTOUIC("SKIP_AUTOUIC")
  , SKIP_AUTORCC("SKIP_AUTORCC")
  , AUTOUIC_OPTIONS("AUTOUIC_OPTIONS")
  , AUTORCC_OPTIONS("AUTORCC_OPTIONS")
  , qrc("qrc")
  , ui("ui")
{
}

cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
  std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators)
{
  for (auto const& localGen : localGenerators) {
    // Detect global autogen and autorcc target names
    bool globalAutoGenTarget = false;
    bool globalAutoRccTarget = false;
    {
      cmMakefile const* makefile = localGen->GetMakefile();
      // Detect global autogen target name
      if (makefile->IsOn("CMAKE_GLOBAL_AUTOGEN_TARGET")) {
        std::string targetName =
          makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME");
        if (targetName.empty()) {
          targetName = "autogen";
        }
        this->GlobalAutoGenTargets_.emplace(localGen.get(),
                                            std::move(targetName));
        globalAutoGenTarget = true;
      }

      // Detect global autorcc target name
      if (makefile->IsOn("CMAKE_GLOBAL_AUTORCC_TARGET")) {
        std::string targetName =
          makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME");
        if (targetName.empty()) {
          targetName = "autorcc";
        }
        this->GlobalAutoRccTargets_.emplace(localGen.get(),
                                            std::move(targetName));
        globalAutoRccTarget = true;
      }
    }

    // Find targets that require AUTOMOC/UIC/RCC processing
    for (auto const& target : localGen->GetGeneratorTargets()) {
      // Process only certain target types
      switch (target->GetType()) {
        case cmStateEnums::EXECUTABLE:
        case cmStateEnums::STATIC_LIBRARY:
        case cmStateEnums::SHARED_LIBRARY:
        case cmStateEnums::MODULE_LIBRARY:
        case cmStateEnums::OBJECT_LIBRARY:
          // Process target
          break;
        default:
          // Don't process target
          continue;
      }
      if (target->IsImported()) {
        // Don't process target
        continue;
      }
      std::set<std::string> const& languages =
        target->GetAllConfigCompileLanguages();
      // cmGeneratorTarget::GetAllConfigCompileLanguages caches the target's
      // sources. Clear it so that OBJECT library targets that are AUTOGEN
      // initialized after this target get their added mocs_compilation.cpp
      // source acknowledged by this target.
      target->ClearSourcesCache();
      if (languages.count("CSharp")) {
        // Don't process target if it's a CSharp target
        continue;
      }

      bool const moc = target->GetPropertyAsBool(this->kw().AUTOMOC);
      bool const uic = target->GetPropertyAsBool(this->kw().AUTOUIC);
      bool const rcc = target->GetPropertyAsBool(this->kw().AUTORCC);
      if (moc || uic || rcc) {
        std::string const& mocExec =
          target->GetSafeProperty(this->kw().AUTOMOC_EXECUTABLE);
        std::string const& uicExec =
          target->GetSafeProperty(this->kw().AUTOUIC_EXECUTABLE);
        std::string const& rccExec =
          target->GetSafeProperty(this->kw().AUTORCC_EXECUTABLE);

        // We support Qt4, Qt5 and Qt6
        auto const qtVersion =
          cmQtAutoGenInitializer::GetQtVersion(target.get(), mocExec);
        bool const validQt = (qtVersion.first.Major == 4) ||
          (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6);

        bool const mocAvailable = (validQt || !mocExec.empty());
        bool const uicAvailable = (validQt || !uicExec.empty());
        bool const rccAvailable = (validQt || !rccExec.empty());
        bool const mocIsValid = (moc && mocAvailable);
        bool const uicIsValid = (uic && uicAvailable);
        bool const rccIsValid = (rcc && rccAvailable);
        // Disabled AUTOMOC/UIC/RCC warning
        bool const mocDisabled = (moc && !mocAvailable);
        bool const uicDisabled = (uic && !uicAvailable);
        bool const rccDisabled = (rcc && !rccAvailable);
        if (mocDisabled || uicDisabled || rccDisabled) {
          cmAlphaNum version = (qtVersion.second == 0)
            ? cmAlphaNum("<QTVERSION>")
            : cmAlphaNum(qtVersion.second);
          cmAlphaNum component = uicDisabled ? "Widgets" : "Core";

          std::string const msg = cmStrCat(
            "AUTOGEN: No valid Qt version found for target ",
            target->GetName(), ".  ",
            cmQtAutoGen::Tools(mocDisabled, uicDisabled, rccDisabled),
            " disabled.  Consider adding:\n  find_package(Qt", version,
            " COMPONENTS ", component, ")\nto your CMakeLists.txt file.");
          target->Makefile->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, msg);
        }
        if (mocIsValid || uicIsValid || rccIsValid) {
          // Create autogen target initializer
          this->Initializers_.emplace_back(
            cm::make_unique<cmQtAutoGenInitializer>(
              this, target.get(), qtVersion.first, mocIsValid, uicIsValid,
              rccIsValid, globalAutoGenTarget, globalAutoRccTarget));
        }
      }
    }
  }
}

cmQtAutoGenGlobalInitializer::~cmQtAutoGenGlobalInitializer() = default;

void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
  cmLocalGenerator* localGen, std::string const& name,
  std::string const& comment)
{
  // Test if the target already exists
  if (!localGen->FindGeneratorTargetToUse(name)) {
    cmMakefile const* makefile = localGen->GetMakefile();

    // Create utility target
    auto cc = cm::make_unique<cmCustomCommand>();
    cc->SetWorkingDirectory(makefile->GetHomeOutputDirectory().c_str());
    cc->SetEscapeOldStyle(false);
    cc->SetComment(comment.c_str());
    cmTarget* target = localGen->AddUtilityCommand(name, true, std::move(cc));
    localGen->AddGeneratorTarget(
      cm::make_unique<cmGeneratorTarget>(target, localGen));

    // Set FOLDER property in the target
    {
      cmValue folder =
        makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
      if (folder) {
        target->SetProperty("FOLDER", folder);
      }
    }
  }
}

void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen(
  cmLocalGenerator* localGen, std::string const& targetName)
{
  auto const it = this->GlobalAutoGenTargets_.find(localGen);
  if (it != this->GlobalAutoGenTargets_.end()) {
    cmGeneratorTarget const* target =
      localGen->FindGeneratorTargetToUse(it->second);
    if (target) {
      target->Target->AddUtility(targetName, false, localGen->GetMakefile());
    }
  }
}

void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc(
  cmLocalGenerator* localGen, std::string const& targetName)
{
  auto const it = this->GlobalAutoRccTargets_.find(localGen);
  if (it != this->GlobalAutoRccTargets_.end()) {
    cmGeneratorTarget const* target =
      localGen->FindGeneratorTargetToUse(it->second);
    if (target) {
      target->Target->AddUtility(targetName, false, localGen->GetMakefile());
    }
  }
}

cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle>
cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
  std::string const& generator, cmQtAutoGen::ConfigString const& executable,
  std::string& error, bool const isMultiConfig, bool const UseBetterGraph)
{
  cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle> res;
  if (isMultiConfig && UseBetterGraph) {
    for (auto const& config : executable.Config) {
      auto const exe = config.second;
      // Check if we have cached features
      {
        auto it = this->CompilerFeatures_.Config[config.first].find(exe);
        if (it != this->CompilerFeatures_.Config[config.first].end()) {
          res.Config[config.first] = it->second;
          continue;
        }
      }

      // Check if the executable exists
      if (!cmSystemTools::FileExists(exe, true)) {
        error = cmStrCat("The \"", generator, "\" executable ",
                         cmQtAutoGen::Quoted(exe), " does not exist.");
        res.Config[config.first] = {};
        continue;
      }

      // Test the executable
      std::string stdOut;
      {
        std::string stdErr;
        std::vector<std::string> command;
        command.emplace_back(exe);
        command.emplace_back("-h");
        int retVal = 0;
        bool const runResult = cmSystemTools::RunSingleCommand(
          command, &stdOut, &stdErr, &retVal, nullptr,
          cmSystemTools::OUTPUT_NONE, cmDuration::zero(),
          cmProcessOutput::Auto);
        if (!runResult) {
          error = cmStrCat("Test run of \"", generator, "\" executable ",
                           cmQtAutoGen::Quoted(exe), " failed.\n",
                           cmQtAutoGen::QuotedCommand(command), '\n', stdOut,
                           '\n', stdErr);
          res.Config[config.first] = {};
          continue;
        }
      }

      // Create valid handle
      res.Config[config.first] =
        std::make_shared<cmQtAutoGen::CompilerFeatures>();
      res.Config[config.first]->HelpOutput = std::move(stdOut);

      // Register compiler features
      this->CompilerFeatures_.Config[config.first].emplace(
        exe, res.Config[config.first]);
    }
    return res;
  }

  // Check if we have cached features
  {
    auto const it = this->CompilerFeatures_.Default.find(executable.Default);
    if (it != this->CompilerFeatures_.Default.end()) {
      res.Default = it->second;
      return res;
    }
  }

  // Check if the executable exists
  if (!cmSystemTools::FileExists(executable.Default, true)) {
    error =
      cmStrCat("The \"", generator, "\" executable ",
               cmQtAutoGen::Quoted(executable.Default), " does not exist.");
    return cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle>();
  }

  // Test the executable
  std::string stdOut;
  {
    std::string stdErr;
    std::vector<std::string> command;
    command.emplace_back(executable.Default);
    command.emplace_back("-h");
    int retVal = 0;
    bool const runResult = cmSystemTools::RunSingleCommand(
      command, &stdOut, &stdErr, &retVal, nullptr, cmSystemTools::OUTPUT_NONE,
      cmDuration::zero(), cmProcessOutput::Auto);
    if (!runResult) {
      error = cmStrCat("Test run of \"", generator, "\" executable ",
                       cmQtAutoGen::Quoted(executable.Default), " failed.\n",
                       cmQtAutoGen::QuotedCommand(command), '\n', stdOut, '\n',
                       stdErr);
      return cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle>();
    }
  }

  res.Default = std::make_shared<cmQtAutoGen::CompilerFeatures>();
  res.Default->HelpOutput = std::move(stdOut);

  // Register compiler features
  this->CompilerFeatures_.Default.emplace(executable.Default, res.Default);

  return res;
}

bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
{
  // Initialize global autogen targets
  {
    std::string const comment = "Global AUTOGEN target";
    for (auto const& pair : this->GlobalAutoGenTargets_) {
      this->GetOrCreateGlobalTarget(pair.first, pair.second, comment);
    }
  }
  // Initialize global autorcc targets
  {
    std::string const comment = "Global AUTORCC target";
    for (auto const& pair : this->GlobalAutoRccTargets_) {
      this->GetOrCreateGlobalTarget(pair.first, pair.second, comment);
    }
  }
  // Initialize per target autogen targets
  for (auto& initializer : this->Initializers_) {
    if (!initializer->InitCustomTargets()) {
      return false;
    }
  }
  return true;
}

bool cmQtAutoGenGlobalInitializer::SetupCustomTargets()
{
  for (auto& initializer : this->Initializers_) {
    if (!initializer->SetupCustomTargets()) {
      return false;
    }
  }
  return true;
}
