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

#include <algorithm>
#include <iterator>
#include <map>
#include <unordered_set>
#include <utility>
#include <vector>

#include <cm/memory>
#include <cm/optional>
#include <cmext/algorithm>

#include "cmFileSet.h"
#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGenExEvaluation.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionNode.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"

cmGeneratorFileSets::cmGeneratorFileSets(cmGeneratorTarget* target,
                                         cmLocalGenerator* lg)
  : Target(target)
  , LocalGenerator(lg)
{
  bool isFramework = target->IsFrameworkOnApple();
  auto issueMessage = [&target](cmFileSet const* fileSet) {
    target->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat(R"(The file set ")", fileSet->GetName(), R"(",  of type ")",
               fileSet->GetType(),
               R"(", is incompatible with the "FRAMEWORK" target ")",
               target->GetName(), R"(".)"));
  };

  for (auto const& name : target->Target->GetAllPrivateFileSets()) {
    cmFileSet const* fileSet = target->Target->GetFileSet(name);
    if (isFramework &&
        !cm::FileSetMetadata::IsFrameworkSupported(fileSet->GetType())) {
      issueMessage(fileSet);
      continue;
    }
    auto entry = this->FileSets.emplace(
      name, cm::make_unique<cmGeneratorFileSet>(target, fileSet));
    auto const* genFileSet = entry.first->second.get();
    this->AllFileSets.push_back(genFileSet);
    this->SelfFileSets[genFileSet->GetType()].push_back(genFileSet);
  }
  for (auto const& name : target->Target->GetAllInterfaceFileSets()) {
    auto it = this->FileSets.find(name);
    cmGeneratorFileSet const* genFileSet = nullptr;
    if (it == this->FileSets.end()) {
      cmFileSet const* fileSet = target->Target->GetFileSet(name);
      if (isFramework &&
          !cm::FileSetMetadata::IsFrameworkSupported(fileSet->GetType())) {
        issueMessage(fileSet);
        continue;
      }
      auto entry = this->FileSets.emplace(
        name, cm::make_unique<cmGeneratorFileSet>(target, fileSet));
      genFileSet = entry.first->second.get();
      this->AllFileSets.push_back(genFileSet);
    } else {
      genFileSet = it->second.get();
    }
    this->InterfaceFileSets[genFileSet->GetType()].push_back(genFileSet);
  }
}
cmGeneratorFileSets::~cmGeneratorFileSets() = default;

std::vector<cm::string_view> cmGeneratorFileSets::GetFileSetTypes() const
{
  return cm::keys(this->SelfFileSets);
}

std::vector<cm::string_view> cmGeneratorFileSets::GetInterfaceFileSetTypes()
  const
{
  return cm::keys(this->InterfaceFileSets);
}

std::vector<cmGeneratorFileSet const*> const&
cmGeneratorFileSets::GetAllFileSets() const
{
  return this->AllFileSets;
}

namespace {
std::vector<cmGeneratorFileSet const*> NoFileSets;
}

std::vector<cmGeneratorFileSet const*> const& cmGeneratorFileSets::GetFileSets(
  cm::string_view type) const
{
  auto it = this->SelfFileSets.find(type);
  if (it != this->SelfFileSets.end()) {
    return it->second;
  }
  return NoFileSets;
}
std::vector<cmGeneratorFileSet const*> const&
cmGeneratorFileSets::GetInterfaceFileSets(cm::string_view type) const
{
  auto it = this->InterfaceFileSets.find(type);
  if (it != this->InterfaceFileSets.end()) {
    return it->second;
  }
  return NoFileSets;
}

cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSet(
  std::string const& name) const
{
  auto const it = this->FileSets.find(name);
  if (it != this->FileSets.end()) {
    return it->second.get();
  }
  return nullptr;
}

std::unordered_set<cmGeneratorFileSet const*> const&
cmGeneratorFileSets::GetAllFileSetsForSource(std::string const& config,
                                             std::string const& path) const
{
  this->BuildInfoCache(config);

  auto const& info = this->Configs[config];

  auto const it = info.FileSetCache.find(path);
  if (it != info.FileSetCache.end()) {
    return it->second;
  }

  // search in all the dependents
  auto const it2 = info.InterfaceFileSetCache.find(path);
  if (it2 != info.InterfaceFileSetCache.end()) {
    return it2->second;
  }

  static std::unordered_set<cmGeneratorFileSet const*> emptySet;
  return emptySet;
}
std::unordered_set<cmGeneratorFileSet const*> const&
cmGeneratorFileSets::GetAllFileSetsForSource(std::string const& config,
                                             cmSourceFile const* sf) const
{
  return this->GetAllFileSetsForSource(config, sf->GetFullPath());
}

cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
  std::string const& config, std::string const& file) const
{
  auto const& fileSets = this->GetAllFileSetsForSource(config, file);
  if (fileSets.empty()) {
    return nullptr;
  }
  return *fileSets.begin();
}
cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
  std::string const& config, cmSourceFile const* sf) const
{
  return this->GetFileSetForSource(config, sf->GetFullPath());
}

std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
cmGeneratorFileSets::GetSources(
  std::function<bool(cmGeneratorFileSet const*)> include,
  cm::GenEx::Context const& context, cmGeneratorTarget const* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  std::vector<std::unique_ptr<TargetPropertyEntry>> entries;

  for (auto const& entry : this->FileSets) {
    auto const* fileSet = entry.second.get();
    if (include(fileSet)) {
      auto sources = fileSet->GetSources(context, target, dagChecker);
      std::move(sources.begin(), sources.end(), std::back_inserter(entries));
    }
  }

  return entries;
}

std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
cmGeneratorFileSets::GetSources(
  cm::GenEx::Context const& context, cmGeneratorTarget const* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  return this->GetSources(
    [](cmGeneratorFileSet const* fileSet) -> bool {
      return fileSet->IsForSelf();
    },
    context, target, dagChecker);
}
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
cmGeneratorFileSets::GetSources(
  std::string type, cm::GenEx::Context const& context,
  cmGeneratorTarget const* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  return this->GetSources(
    [&type](cmGeneratorFileSet const* fileSet) -> bool {
      return fileSet->IsForSelf() && fileSet->GetType() == type;
    },
    context, target, dagChecker);
}

std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
cmGeneratorFileSets::GetInterfaceSources(
  cm::GenEx::Context const& context, cmGeneratorTarget const* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  return this->GetSources(
    [](cmGeneratorFileSet const* fileSet) -> bool {
      return fileSet->IsForInterface();
    },
    context, target, dagChecker);
}
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
cmGeneratorFileSets::GetInterfaceSources(
  std::string type, cm::GenEx::Context const& context,
  cmGeneratorTarget const* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  return this->GetSources(
    [&type](cmGeneratorFileSet const* fileSet) -> bool {
      return fileSet->IsForInterface() && fileSet->GetType() == type;
    },
    context, target, dagChecker);
}

bool cmGeneratorFileSets::MaybeHaveInterfaceProperty(
  cm::string_view type, std::string const& prop,
  cm::GenEx::Evaluation* eval) const
{
  std::string const key =
    cmStrCat(type, "::", prop, '@', eval->Context.Config);
  auto i = this->MaybeInterfacePropertyExists.find(key);
  if (i == this->MaybeInterfacePropertyExists.end()) {
    // Insert an entry now in case there is a cycle.
    i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
    bool& maybeInterfaceProp = i->second;

    for (auto const* fileSet : this->GetInterfaceFileSets(type)) {
      // If this file set itself has a non-empty property value, we are done.
      maybeInterfaceProp = !fileSet->GetProperty(prop).IsEmpty();
      if (maybeInterfaceProp) {
        break;
      }
    }

    // Otherwise, recurse to interface dependencies.
    if (!maybeInterfaceProp) {
      cmGeneratorTarget const* headTarget =
        eval->HeadTarget ? eval->HeadTarget : this->Target;
      if (cmLinkInterfaceLibraries const* iface =
            this->Target->GetLinkInterfaceLibraries(
              eval->Context.Config, headTarget,
              cmGeneratorTarget::UseTo::Compile)) {
        if (iface->HadHeadSensitiveCondition) {
          // With a different head target we may get to a library with
          // this interface property.
          maybeInterfaceProp = true;
        } else {
          // The transitive interface libraries do not depend on the
          // head target, so we can follow them.
          for (cmLinkItem const& lib : iface->Libraries) {
            if (lib.Target &&
                lib.Target->GetGeneratorFileSets()->MaybeHaveInterfaceProperty(
                  type, prop, eval)) {
              maybeInterfaceProp = true;
              break;
            }
          }
        }
      }
    }
  }
  return i->second;
}

std::string cmGeneratorFileSets::EvaluateInterfaceProperty(
  cm::string_view type, std::string const& prop, cm::GenEx::Evaluation* eval,
  cmGeneratorExpressionDAGChecker* dagCheckerParent) const
{
  // If the property does not appear transitively at all, we are done.
  if (!this->MaybeHaveInterfaceProperty(type, prop, eval)) {
    return std::string{};
  }

  cmList result;
  cmGeneratorExpressionDAGChecker dagChecker{
    this->Target,     prop,          nullptr,
    dagCheckerParent, eval->Context, eval->Backtrace,
  };
  switch (dagChecker.Check()) {
    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
      dagChecker.ReportError(
        eval,
        cmStrCat("$<FILE_SET_PROPERTY:*,TARGET:", this->Target->GetName(), ',',
                 prop, '>'));
      return std::string{};
    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
      // No error. We just skip cyclic references.
    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
      // No error. We have already seen this transitive property.
      return std::string{};
    case cmGeneratorExpressionDAGChecker::DAG:
      break;
  }

  cmGeneratorTarget const* headTarget =
    eval->HeadTarget ? eval->HeadTarget : this->Target;

  for (auto const* fileSet : this->GetInterfaceFileSets(type)) {
    if (cmValue p = fileSet->GetProperty(prop)) {
      result.append(cmGeneratorExpressionNode::EvaluateDependentExpression(
        *p, eval, headTarget, &dagChecker, this->Target));
    }
  }

  if (cmLinkInterfaceLibraries const* iface =
        this->Target->GetLinkInterfaceLibraries(
          eval->Context.Config, headTarget,
          cmGeneratorTarget::UseTo::Compile)) {
    eval->HadContextSensitiveCondition = eval->HadContextSensitiveCondition ||
      iface->HadContextSensitiveCondition;
    for (cmLinkItem const& lib : iface->Libraries) {
      // Broken code can have a target in its own link interface.
      // Don't follow such link interface entries so as not to create a
      // self-referencing loop.
      if (lib.Target && lib.Target != this->Target) {
        // Pretend $<FILE_SET__PROPERTY:fileSet,TARGET:lib.Target,prop>
        // appeared in the above property and hand-evaluate it as if it were
        // compiled.
        // Create a context as cmCompiledGeneratorExpression::Evaluate does.
        cm::GenEx::Evaluation libEval(
          eval->Context, eval->Quiet, headTarget, this->Target,
          eval->EvaluateForBuildsystem, eval->Backtrace);
        std::string libResult = cmGeneratorExpression::StripEmptyListElements(
          lib.Target->GetGeneratorFileSets()->EvaluateInterfaceProperty(
            type, prop, &libEval, &dagChecker));
        if (!libResult.empty()) {
          result.append(libResult);
        }
        eval->HadContextSensitiveCondition =
          eval->HadContextSensitiveCondition ||
          libEval.HadContextSensitiveCondition;
        eval->HadHeadSensitiveCondition =
          eval->HadHeadSensitiveCondition || libEval.HadHeadSensitiveCondition;
      }
    }
  }

  return result.to_string();
}

namespace {
void GetInterfaceFiles(
  cmGeneratorTarget const* target, cm::GenEx::Context const& context,
  std::unordered_set<cmGeneratorTarget const*>& targets,
  std::map<std::string, std::unordered_set<cmGeneratorFileSet const*>>& cache)
{
  namespace Metadata = cm::FileSetMetadata;

  for (auto const& type : Metadata::GetKnownTypes()) {
    auto fileSetDescriptor = Metadata::GetFileSetDescriptor(type);
    if (fileSetDescriptor &&
        fileSetDescriptor->Lookup == Metadata::FileSetLookup::Dependencies) {
      for (auto const* fileSet : target->GetInterfaceFileSets(type)) {
        auto files = fileSet->GetFiles(context, target);

        for (auto const& it : files.first) {
          for (auto const& filename : it.second) {
            auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
            cache[collapsedFile].insert(fileSet);
          }
        }
      }
    }
  }

  if (cmLinkInterfaceLibraries const* iface =
        target->GetLinkInterfaceLibraries(context.Config, target,
                                          cmGeneratorTarget::UseTo::Compile)) {
    for (cmLinkItem const& lib : iface->Libraries) {
      if (lib.Target && lib.Target != target &&
          targets.insert(lib.Target).second) {
        GetInterfaceFiles(lib.Target, context, targets, cache);
      }
    }
  }
}
}

void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const
{
  auto& info = this->Configs[config];

  if (info.BuiltCache) {
    return;
  }

  cm::GenEx::Context context(this->LocalGenerator, config);

  for (auto const& item : this->FileSets) {
    auto const* fileSet = item.second.get();

    auto files = fileSet->GetFiles(context, this->Target);

    for (auto const& it : files.first) {
      for (auto const& filename : it.second) {
        auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
        info.FileSetCache[collapsedFile].insert(fileSet);
      }
    }
  }

  // retrieve all files inherited from dependent targets
  std::unordered_set<cmGeneratorTarget const*> targets;

  if (cmLinkImplementationLibraries const* impl =
        this->Target->GetLinkImplementationLibraries(
          config, cmGeneratorTarget::UseTo::Compile)) {
    for (cmLinkItem const& lib : impl->Libraries) {
      if (lib.Target) {
        GetInterfaceFiles(lib.Target, context, targets,
                          info.InterfaceFileSetCache);
      }
    }
  }

  info.BuiltCache = true;
}
