/* 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 <utility>
#include <vector>

#include <cmext/string_view>

#include "cmsys/RegularExpression.hxx"

#include "cmGeneratorExpression.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;
}

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

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 : cmExpandedList(entry.Value)) {
      cmGeneratorExpression ge(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 : cmExpandedList(entry.Value)) {
      cmGeneratorExpression ge(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
{
  std::vector<std::string> result;
  for (auto const& cge : cges) {
    auto entry = cge->Evaluate(lg, config, target, dagChecker);
    auto dirs = cmExpandedList(entry);
    for (std::string dir : dirs) {
      if (!cmSystemTools::FileIsFullPath(dir)) {
        dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir);
      }
      auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
      for (auto const& priorDir : result) {
        auto collapsedPriorDir = cmSystemTools::CollapseFullPath(priorDir);
        if (!cmSystemTools::SameFile(collapsedDir, collapsedPriorDir) &&
            (cmSystemTools::IsSubDirectory(collapsedDir, collapsedPriorDir) ||
             cmSystemTools::IsSubDirectory(collapsedPriorDir, 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 : cmExpandedList(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);
}
