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

#include <set>
#include <utility>

#include <cm/memory>

#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProcessOutput.h"
#include "cmProperty.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenInitializer.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.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 (const auto& localGen : localGenerators) {
    // Detect global autogen and autorcc target names
    bool globalAutoGenTarget = false;
    bool globalAutoRccTarget = false;
    {
      cmMakefile* 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 (const auto& 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 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, ")\n", "to your CMakeLists.txt file.");
          target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, 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) == nullptr) {
    cmMakefile* makefile = localGen->GetMakefile();

    // Create utility target
    std::vector<std::string> no_byproducts;
    std::vector<std::string> no_depends;
    cmCustomCommandLines no_commands;
    const cmPolicies::PolicyStatus cmp0116_new = cmPolicies::NEW;
    cmTarget* target = localGen->AddUtilityCommand(
      name, true, makefile->GetHomeOutputDirectory().c_str(), no_byproducts,
      no_depends, no_commands, cmp0116_new, false, comment.c_str());
    localGen->AddGeneratorTarget(
      cm::make_unique<cmGeneratorTarget>(target, localGen));

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

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

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

cmQtAutoGen::CompilerFeaturesHandle
cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
  std::string const& generator, std::string const& executable,
  std::string& error)
{
  // Check if we have cached features
  {
    auto it = this->CompilerFeatures_.find(executable);
    if (it != this->CompilerFeatures_.end()) {
      return it->second;
    }
  }

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

  // Test the executable
  std::string stdOut;
  {
    std::string stdErr;
    std::vector<std::string> command;
    command.emplace_back(executable);
    command.emplace_back("-h");
    int retVal = 0;
    const bool 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), " failed.\n",
                       cmQtAutoGen::QuotedCommand(command), '\n', stdOut, '\n',
                       stdErr);
      return cmQtAutoGen::CompilerFeaturesHandle();
    }
  }

  // Create valid handle
  cmQtAutoGen::CompilerFeaturesHandle res =
    std::make_shared<cmQtAutoGen::CompilerFeatures>();
  res->HelpOutput = std::move(stdOut);

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

  return res;
}

bool cmQtAutoGenGlobalInitializer::generate()
{
  return (this->InitializeCustomTargets() && this->SetupCustomTargets());
}

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;
}
