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

#include <map>
#include <utility>

#include <cm/memory>
#include <cm/string_view>
#include <cmext/string_view>

#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.h"
#include "cmValue.h"

cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
  cmGlobalGenerator* gg, std::vector<std::string> const& targets,
  cmMakefile* mf, std::set<std::string> const& langs)
  : Languages(langs.begin(), langs.end())
{
  gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
}

void cmExportTryCompileFileGenerator::IssueMessage(
  MessageType type, std::string const& message) const
{
  switch (type) {
    case MessageType::FATAL_ERROR:
    case MessageType::INTERNAL_ERROR:
      cmSystemTools::Error(message);
      break;
    case MessageType::WARNING:
      cmSystemTools::Message(cmStrCat("CMake Warning: "_s, message),
                             "Warning");
      break;
    default:
      cmSystemTools::Message(message);
  }
}

void cmExportTryCompileFileGenerator::IssueDiagnostic(
  cmDiagnosticCategory category, std::string const& message) const
{
  cm::string_view const cname =
    cmDiagnostics::GetCategoryString(category).substr(4);
  cmSystemTools::Message(
    cmStrCat("CMake Diagnostic ("_s, cname, "): "_s, message), "Diagnostic");
}

bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
{
  std::set<cmGeneratorTarget const*> emitted;
  std::set<cmGeneratorTarget const*> emittedDeps;
  while (!this->Exports.empty()) {
    cmGeneratorTarget const* te = this->Exports.back();
    this->Exports.pop_back();
    if (emitted.insert(te).second) {
      emittedDeps.insert(te);
      this->GenerateImportTargetCode(os, te, te->GetType());

      ImportPropertyMap properties;

      for (std::string const& lang : this->Languages) {
        for (auto i : cmGeneratorTarget::BuiltinTransitiveProperties) {
          this->FindTargets(std::string(i.second.InterfaceName), te, lang,
                            emittedDeps);
        }
      }

      this->PopulateProperties(te, properties, emittedDeps);

      this->GenerateInterfaceProperties(te, os, properties);
    }
  }
  return true;
}

std::string cmExportTryCompileFileGenerator::FindTargets(
  std::string const& propName, cmGeneratorTarget const* tgt,
  std::string const& language, std::set<cmGeneratorTarget const*>& emitted)
{
  cmValue prop = tgt->GetProperty(propName);
  if (!prop) {
    return std::string();
  }

  cm::GenEx::Context context(tgt->LocalGenerator, this->Config, language);

  cmGeneratorExpression ge(*tgt->Makefile->GetCMakeInstance());

  std::unique_ptr<cmGeneratorExpressionDAGChecker> parentDagChecker;
  if (propName == "INTERFACE_LINK_OPTIONS") {
    // To please constraint checks of DAGChecker, this property must have
    // LINK_OPTIONS property as parent
    parentDagChecker = cm::make_unique<cmGeneratorExpressionDAGChecker>(
      tgt, "LINK_OPTIONS", nullptr, nullptr, context);
  }
  cmGeneratorExpressionDAGChecker dagChecker{
    tgt, propName, nullptr, parentDagChecker.get(), context,
  };

  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*prop);

  cmTarget dummyHead("try_compile_dummy_exe", cm::TargetType::EXECUTABLE,
                     cmTarget::Visibility::Normal, tgt->Target->GetMakefile(),
                     cmTarget::PerConfig::Yes);
  dummyHead.SetIsForTryCompile();

  cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());

  std::string result = cge->Evaluate(context, &dagChecker, &gDummyHead, tgt);

  std::set<cmGeneratorTarget const*> const& allTargets =
    cge->GetAllTargetsSeen();
  for (cmGeneratorTarget const* target : allTargets) {
    if (emitted.insert(target).second) {
      this->Exports.push_back(target);
    }
  }
  return result;
}

void cmExportTryCompileFileGenerator::PopulateProperties(
  cmGeneratorTarget const* target, ImportPropertyMap& properties,
  std::set<cmGeneratorTarget const*>& emitted)
{
  // Look through all non-special properties.
  std::vector<std::string> props = target->GetPropertyKeys();
  // Include special properties that might be relevant here.
  props.emplace_back("INTERFACE_LINK_LIBRARIES");
  props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT");
  props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE");
  for (std::string const& p : props) {
    cmValue v = target->GetProperty(p);
    if (!v) {
      continue;
    }
    properties[p] = *v;

    if (cmHasLiteralPrefix(p, "IMPORTED_LINK_INTERFACE_LIBRARIES") ||
        cmHasLiteralPrefix(p, "IMPORTED_LINK_DEPENDENT_LIBRARIES") ||
        cmHasLiteralPrefix(p, "INTERFACE_LINK_LIBRARIES")) {
      std::string evalResult =
        this->FindTargets(p, target, std::string(), emitted);

      cmList depends{ evalResult };
      for (std::string const& li : depends) {
        cmGeneratorTarget* tgt =
          target->GetLocalGenerator()->FindGeneratorTargetToUse(li);
        if (tgt && emitted.insert(tgt).second) {
          this->Exports.push_back(tgt);
        }
      }
    }
  }
}

std::string cmExportTryCompileFileGenerator::InstallNameDir(
  cmGeneratorTarget const* target, std::string const& config)
{
  std::string install_name_dir;

  cmMakefile* mf = target->Target->GetMakefile();
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
    install_name_dir = target->GetInstallNameDirForBuildTree(config);
  }

  return install_name_dir;
}

std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
  cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet,
  cmTargetExport const* /*te*/)
{
  return cmOutputConverter::EscapeForCMake(
    cmList::to_string(fileSet->GetDirectoryEntries()));
}

std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
  cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet,
  cmTargetExport const* /*te*/)
{
  return cmOutputConverter::EscapeForCMake(
    cmList::to_string(fileSet->GetFileEntries()));
}
