/* 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 <cmext/enum_set>

#include "cmFileSet.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 "cmLocalGenerator.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 domain : cm::FileSetMetadata::AllFileSetDomains) {
    for (auto const& name : target->Target->GetAllPrivateFileSets(domain)) {
      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, domain));
      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(domain)) {
      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, domain));
        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
{
  this->BuildInfoCache(config);
  auto const& info = this->Configs[config];

  using FileSetCache =
    std::map<std::string, std::unordered_set<cmGeneratorFileSet const*>>;
  auto lookup = [&file](FileSetCache const& cache, bool nonHeaderOnly) {
    auto const entry = cache.find(file);
    if (entry == cache.end()) {
      return static_cast<cmGeneratorFileSet const*>(nullptr);
    }
    auto const fileSet =
      std::find_if(entry->second.begin(), entry->second.end(),
                   [nonHeaderOnly](cmGeneratorFileSet const* candidate) {
                     return !nonHeaderOnly ||
                       candidate->GetType() != cm::FileSetMetadata::HEADERS;
                   });
    return fileSet == entry->second.end() ? nullptr : *fileSet;
  };

  if (auto const* fileSet = lookup(info.FileSetCache, true)) {
    return fileSet;
  }
  if (auto const* fileSet = lookup(info.InterfaceFileSetCache, true)) {
    return fileSet;
  }
  if (auto const* fileSet = lookup(info.FileSetCache, false)) {
    return fileSet;
  }
  return lookup(info.InterfaceFileSetCache, false);
}
cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
  std::string const& config, cmSourceFile const* sf) const
{
  return this->GetFileSetForSource(config, sf->GetFullPath());
}

cm::optional<std::string> cmGeneratorFileSets::GetLanguageForSource(
  std::string const& config, cmSourceFile const* sf) const
{
  this->BuildInfoCache(config);
  auto const& languages = this->Configs[config].LanguageCache;
  auto const language = languages.find(sf->GetFullPath());
  if (language == languages.end()) {
    return cm::nullopt;
  }
  return language->second;
}

bool cmGeneratorFileSets::HasSyclHeaders(std::string const& config) const
{
  this->BuildInfoCache(config);
  return this->Configs[config].HasSyclHeaders;
}

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,
  cm::FileSetMetadata::FileSetDomainSet domains,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  return this->GetSources(
    [&domains](cmGeneratorFileSet const* fileSet) -> bool {
      return fileSet->IsForSelf() && domains.contains(fileSet->GetDomain());
    },
    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,
  cm::FileSetMetadata::FileSetDomainSet domains,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  return this->GetSources(
    [&domains](cmGeneratorFileSet const* fileSet) -> bool {
      return fileSet->IsForInterface() &&
        domains.contains(fileSet->GetDomain());
    },
    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, cmGeneratorTarget const* headTarget,
  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, headTarget);

        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, headTarget,
                                          cmGeneratorTarget::UseTo::Compile)) {
    for (cmLinkItem const& lib : iface->Libraries) {
      if (lib.Target && lib.Target != target &&
          targets.insert(lib.Target).second) {
        GetInterfaceFiles(lib.Target, headTarget, context, targets, cache);
      }
    }
  }
}

bool HasInterfaceSyclHeaders(
  cmGeneratorTarget const* target, cmGeneratorTarget const* headTarget,
  std::string const& config,
  std::unordered_set<cmGeneratorTarget const*>& targets)
{
  for (auto const* fileSet :
       target->GetInterfaceFileSets(cm::FileSetMetadata::HEADERS)) {
    if (fileSet->GetProperty("LANGUAGE") == cm::FileSetMetadata::SYCL) {
      return true;
    }
  }

  if (cmLinkInterfaceLibraries const* iface =
        target->GetLinkInterfaceLibraries(config, headTarget,
                                          cmGeneratorTarget::UseTo::Compile)) {
    for (cmLinkItem const& lib : iface->Libraries) {
      if (lib.Target && lib.Target != target &&
          targets.insert(lib.Target).second &&
          HasInterfaceSyclHeaders(lib.Target, headTarget, config, targets)) {
        return true;
      }
    }
  }
  return false;
}
}

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

  if (info.BuiltCache) {
    return;
  }

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

  info.HasSyclHeaders = std::any_of(
    this->GetFileSets(cm::FileSetMetadata::HEADERS).begin(),
    this->GetFileSets(cm::FileSetMetadata::HEADERS).end(),
    [](cmGeneratorFileSet const* fileSet) {
      return fileSet->GetProperty("LANGUAGE") == cm::FileSetMetadata::SYCL;
    });

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

    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;
  std::unordered_set<cmGeneratorTarget const*> syclHeaderTargets;

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

  auto indexLanguages =
    [this,
     &info](std::map<std::string,
                     std::unordered_set<cmGeneratorFileSet const*>> const&
              fileSets) {
      for (auto const& file : fileSets) {
        for (auto const* fileSet : file.second) {
          if (fileSet->GetType() != cm::FileSetMetadata::SOURCES) {
            continue;
          }
          cmValue const language = fileSet->GetProperty("LANGUAGE");
          if (language.IsEmpty()) {
            continue;
          }
          auto const inserted =
            info.LanguageCache.emplace(file.first, *language);
          if (!inserted.second && inserted.first->second != *language) {
            this->LocalGenerator->IssueMessage(
              MessageType::FATAL_ERROR,
              cmStrCat("Source file\n  ", file.first,
                       "\nbelongs to multiple SOURCES file sets with "
                       "conflicting LANGUAGE properties."));
          }
        }
      }
    };
  indexLanguages(info.FileSetCache);
  indexLanguages(info.InterfaceFileSetCache);

  info.BuiltCache = true;
}
