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

#include <memory>
#include <ostream>
#include <set>
#include <string>
#include <utility>
#include <vector>

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

#include "cmGeneratorExpression.h"
#include "cmInstallRuntimeDependencySet.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmScriptGenerator.h"
#include "cmStringAlgorithms.h"

namespace {
template <typename T, typename F>
void WriteMultiArgument(std::ostream& os, cm::string_view const& keyword,
                        std::vector<T> const& list,
                        cmScriptGeneratorIndent indent, F transform)
{
  bool first = true;
  for (auto const& item : list) {
    cm::optional<std::string> result = transform(item);
    if (result) {
      if (first) {
        os << indent << "  " << keyword << "\n";
        first = false;
      }
      os << indent << "    " << *result << "\n";
    }
  }
}

void WriteFilesArgument(
  std::ostream& os, cm::string_view const& keyword,
  std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>> const&
    items,
  std::string const& config, cmScriptGeneratorIndent indent)
{
  WriteMultiArgument(
    os, keyword, items, indent,
    [config](std::unique_ptr<cmInstallRuntimeDependencySet::Item> const& i)
      -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); });
}

void WriteGenexEvaluatorArgument(std::ostream& os,
                                 cm::string_view const& keyword,
                                 std::vector<std::string> const& genexes,
                                 std::string const& config,
                                 cmLocalGenerator* lg,
                                 cmScriptGeneratorIndent indent)
{
  WriteMultiArgument(
    os, keyword, genexes, indent,
    [config, lg](std::string const& genex) -> cm::optional<std::string> {
      std::string result = cmGeneratorExpression::Evaluate(genex, lg, config);
      if (result.empty()) {
        return cm::nullopt;
      }
      return cmOutputConverter::EscapeForCMake(result);
    });
}
}

cmInstallGetRuntimeDependenciesGenerator::
  cmInstallGetRuntimeDependenciesGenerator(
    cmInstallRuntimeDependencySet* runtimeDependencySet,
    std::vector<std::string> directories,
    std::vector<std::string> preIncludeRegexes,
    std::vector<std::string> preExcludeRegexes,
    std::vector<std::string> postIncludeRegexes,
    std::vector<std::string> postExcludeRegexes,
    std::vector<std::string> postIncludeFiles,
    std::vector<std::string> postExcludeFiles, std::string libraryComponent,
    std::string frameworkComponent, bool noInstallRPath, char const* depsVar,
    char const* rpathPrefix, std::vector<std::string> const& configurations,
    MessageLevel message, bool exclude_from_all, cmListFileBacktrace backtrace)
  : cmInstallGenerator("", configurations, "", message, exclude_from_all,
                       false, std::move(backtrace))
  , RuntimeDependencySet(runtimeDependencySet)
  , Directories(std::move(directories))
  , PreIncludeRegexes(std::move(preIncludeRegexes))
  , PreExcludeRegexes(std::move(preExcludeRegexes))
  , PostIncludeRegexes(std::move(postIncludeRegexes))
  , PostExcludeRegexes(std::move(postExcludeRegexes))
  , PostIncludeFiles(std::move(postIncludeFiles))
  , PostExcludeFiles(std::move(postExcludeFiles))
  , LibraryComponent(std::move(libraryComponent))
  , FrameworkComponent(std::move(frameworkComponent))
  , NoInstallRPath(noInstallRPath)
  , DepsVar(depsVar)
  , RPathPrefix(rpathPrefix)
{
  this->ActionsPerConfig = true;
}

bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg)
{
  this->LocalGenerator = lg;
  return true;
}

void cmInstallGetRuntimeDependenciesGenerator::GenerateScript(std::ostream& os)
{
  // Track indentation.
  Indent indent;

  // Begin this block of installation.
  os << indent << "if(";
  if (this->FrameworkComponent.empty() ||
      this->FrameworkComponent == this->LibraryComponent) {
    os << this->CreateComponentTest(this->LibraryComponent,
                                    this->ExcludeFromAll);
  } else {
    os << this->CreateComponentTest(this->LibraryComponent, true) << " OR "
       << this->CreateComponentTest(this->FrameworkComponent,
                                    this->ExcludeFromAll);
  }
  os << ")\n";

  // Generate the script possibly with per-configuration code.
  this->GenerateScriptConfigs(os, indent.Next());

  // End this block of installation.
  os << indent << "endif()\n\n";
}

void cmInstallGetRuntimeDependenciesGenerator::GenerateScriptForConfig(
  std::ostream& os, std::string const& config, Indent indent)
{
  std::string installNameTool =
    this->LocalGenerator->GetMakefile()->GetSafeDefinition(
      "CMAKE_INSTALL_NAME_TOOL");

  os << indent << "file(GET_RUNTIME_DEPENDENCIES\n"
     << indent << "  RESOLVED_DEPENDENCIES_VAR " << this->DepsVar << '\n';
  WriteFilesArgument(os, "EXECUTABLES"_s,
                     this->RuntimeDependencySet->GetExecutables(), config,
                     indent);
  WriteFilesArgument(os, "LIBRARIES"_s,
                     this->RuntimeDependencySet->GetLibraries(), config,
                     indent);
  WriteFilesArgument(os, "MODULES"_s, this->RuntimeDependencySet->GetModules(),
                     config, indent);
  if (this->RuntimeDependencySet->GetBundleExecutable()) {
    os << indent << "  BUNDLE_EXECUTABLE \""
       << this->RuntimeDependencySet->GetBundleExecutable()->GetItemPath(
            config)
       << "\"\n";
  }
  WriteGenexEvaluatorArgument(os, "DIRECTORIES"_s, this->Directories, config,
                              this->LocalGenerator, indent);
  WriteGenexEvaluatorArgument(os, "PRE_INCLUDE_REGEXES"_s,
                              this->PreIncludeRegexes, config,
                              this->LocalGenerator, indent);
  WriteGenexEvaluatorArgument(os, "PRE_EXCLUDE_REGEXES"_s,
                              this->PreExcludeRegexes, config,
                              this->LocalGenerator, indent);
  WriteGenexEvaluatorArgument(os, "POST_INCLUDE_REGEXES"_s,
                              this->PostIncludeRegexes, config,
                              this->LocalGenerator, indent);
  WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_REGEXES"_s,
                              this->PostExcludeRegexes, config,
                              this->LocalGenerator, indent);
  WriteGenexEvaluatorArgument(os, "POST_INCLUDE_FILES"_s,
                              this->PostIncludeFiles, config,
                              this->LocalGenerator, indent);
  WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_FILES"_s,
                              this->PostExcludeFiles, config,
                              this->LocalGenerator, indent);

  std::set<std::string> postExcludeFiles;
  auto const addPostExclude =
    [config, &postExcludeFiles, this](
      std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>> const&
        tgts) {
      for (auto const& item : tgts) {
        item->AddPostExcludeFiles(config, postExcludeFiles,
                                  this->RuntimeDependencySet);
      }
    };
  addPostExclude(this->RuntimeDependencySet->GetExecutables());
  addPostExclude(this->RuntimeDependencySet->GetLibraries());
  addPostExclude(this->RuntimeDependencySet->GetModules());
  bool first = true;
  for (auto const& file : postExcludeFiles) {
    if (first) {
      os << indent << "  POST_EXCLUDE_FILES_STRICT\n";
      first = false;
    }
    os << indent << "    \"" << file << "\"\n";
  }

  if (!installNameTool.empty() && !this->NoInstallRPath) {
    os << indent << "  RPATH_PREFIX " << this->RPathPrefix << '\n';
  }
  os << indent << "  )\n";
}
