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

cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
  std::string const& config, std::string const& path) const
{
  using Lookup = cm::FileSetMetadata::FileSetLookup;

  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() &&
      cm::FileSetMetadata::GetFileSetDescriptor(it2->second->GetType())
          .value_or(cm::FileSetMetadata::FileSetDescriptor{ Lookup::Target })
          .Lookup == Lookup::Dependencies) {
    return it2->second;
  }

  return nullptr;
}
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, 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] = 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] = 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;
}
