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

#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

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

#include "cmsys/RegularExpression.hxx"

#include "cmGeneratorExpression.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"

cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
{
  switch (vis) {
    case cmFileSetVisibility::Interface:
      return "INTERFACE"_s;
    case cmFileSetVisibility::Public:
      return "PUBLIC"_s;
    case cmFileSetVisibility::Private:
      return "PRIVATE"_s;
  }
  return ""_s;
}

cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
                                                cmMakefile* mf)
{
  if (name == "INTERFACE"_s) {
    return cmFileSetVisibility::Interface;
  }
  if (name == "PUBLIC"_s) {
    return cmFileSetVisibility::Public;
  }
  if (name == "PRIVATE"_s) {
    return cmFileSetVisibility::Private;
  }
  auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
  if (mf) {
    mf->IssueMessage(MessageType::FATAL_ERROR, msg);
  } else {
    cmSystemTools::Error(msg);
  }
  return cmFileSetVisibility::Private;
}

bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
{
  switch (vis) {
    case cmFileSetVisibility::Interface:
      return false;
    case cmFileSetVisibility::Public:
    case cmFileSetVisibility::Private:
      return true;
  }
  return false;
}

bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
{
  switch (vis) {
    case cmFileSetVisibility::Interface:
    case cmFileSetVisibility::Public:
      return true;
    case cmFileSetVisibility::Private:
      return false;
  }
  return false;
}

bool cmFileSetTypeCanBeIncluded(std::string const& type)
{
  return type == "HEADERS"_s;
}

cmFileSet::cmFileSet(cmake& cmakeInstance, std::string name, std::string type,
                     cmFileSetVisibility visibility)
  : CMakeInstance(cmakeInstance)
  , Name(std::move(name))
  , Type(std::move(type))
  , Visibility(visibility)
{
}

void cmFileSet::CopyEntries(cmFileSet const* fs)
{
  cm::append(this->DirectoryEntries, fs->DirectoryEntries);
  cm::append(this->FileEntries, fs->FileEntries);
}

void cmFileSet::ClearDirectoryEntries()
{
  this->DirectoryEntries.clear();
}

void cmFileSet::AddDirectoryEntry(BT<std::string> directories)
{
  this->DirectoryEntries.push_back(std::move(directories));
}

void cmFileSet::ClearFileEntries()
{
  this->FileEntries.clear();
}

void cmFileSet::AddFileEntry(BT<std::string> files)
{
  this->FileEntries.push_back(std::move(files));
}

std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
cmFileSet::CompileFileEntries() const
{
  std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;

  for (auto const& entry : this->FileEntries) {
    for (auto const& ex : cmList{ entry.Value }) {
      cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace);
      auto cge = ge.Parse(ex);
      result.push_back(std::move(cge));
    }
  }

  return result;
}

std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
cmFileSet::CompileDirectoryEntries() const
{
  std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;

  for (auto const& entry : this->DirectoryEntries) {
    for (auto const& ex : cmList{ entry.Value }) {
      cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace);
      auto cge = ge.Parse(ex);
      result.push_back(std::move(cge));
    }
  }

  return result;
}

std::vector<std::string> cmFileSet::EvaluateDirectoryEntries(
  const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges,
  cmLocalGenerator* lg, const std::string& config,
  const cmGeneratorTarget* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  struct DirCacheEntry
  {
    std::string collapsedDir;
    cm::optional<cmSystemTools::FileId> fileId;
  };

  std::unordered_map<std::string, DirCacheEntry> dirCache;
  std::vector<std::string> result;
  for (auto const& cge : cges) {
    auto entry = cge->Evaluate(lg, config, target, dagChecker);
    cmList dirs{ entry };
    for (std::string dir : dirs) {
      if (!cmSystemTools::FileIsFullPath(dir)) {
        dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir);
      }

      auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry());
      auto& dirCacheEntry = dirCacheResult.first->second;
      const auto isNewCacheEntry = dirCacheResult.second;

      if (isNewCacheEntry) {
        cmSystemTools::FileId fileId;
        auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId);
        dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir);
        dirCacheEntry.fileId =
          isFileIdValid ? cm::optional<decltype(fileId)>(fileId) : cm::nullopt;
      }

      for (auto const& priorDir : result) {
        auto priorDirCacheEntry = dirCache.at(priorDir);
        bool sameFile = dirCacheEntry.fileId.has_value() &&
          priorDirCacheEntry.fileId.has_value() &&
          (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId);
        if (!sameFile &&
            (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir,
                                           priorDirCacheEntry.collapsedDir) ||
             cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir,
                                           dirCacheEntry.collapsedDir))) {
          lg->GetCMakeInstance()->IssueMessage(
            MessageType::FATAL_ERROR,
            cmStrCat(
              "Base directories in file set cannot be subdirectories of each "
              "other:\n  ",
              priorDir, "\n  ", dir),
            cge->GetBacktrace());
          return {};
        }
      }
      result.push_back(dir);
    }
  }
  return result;
}

void cmFileSet::EvaluateFileEntry(
  const std::vector<std::string>& dirs,
  std::map<std::string, std::vector<std::string>>& filesPerDir,
  const std::unique_ptr<cmCompiledGeneratorExpression>& cge,
  cmLocalGenerator* lg, const std::string& config,
  const cmGeneratorTarget* target,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  auto files = cge->Evaluate(lg, config, target, dagChecker);
  for (std::string file : cmList{ files }) {
    if (!cmSystemTools::FileIsFullPath(file)) {
      file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file);
    }
    auto collapsedFile = cmSystemTools::CollapseFullPath(file);
    bool found = false;
    std::string relDir;
    for (auto const& dir : dirs) {
      auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
      if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
        found = true;
        relDir = cmSystemTools::GetParentDirectory(
          cmSystemTools::RelativePath(collapsedDir, collapsedFile));
        break;
      }
    }
    if (!found) {
      std::ostringstream e;
      e << "File:\n  " << file
        << "\nmust be in one of the file set's base directories:";
      for (auto const& dir : dirs) {
        e << "\n  " << dir;
      }
      lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
                                           cge->GetBacktrace());
      return;
    }

    filesPerDir[relDir].push_back(file);
  }
}

bool cmFileSet::IsValidName(const std::string& name)
{
  static const cmsys::RegularExpression regex("^[a-z0-9][a-zA-Z0-9_]*$");

  cmsys::RegularExpressionMatch match;
  return regex.find(name.c_str(), match);
}
