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

#include "cmInstallScriptHandler.h"

#include <algorithm>
#include <cstddef>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <cm/memory>

#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include <cm3p/uv.h>

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmInstrumentation.h"
#include "cmJSONState.h"
#include "cmProcessOutput.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUVHandlePtr.h"
#include "cmUVProcessChain.h"
#include "cmUVStream.h"

using InstallScript = cmInstallScriptHandler::InstallScript;
using InstallScriptRunner = cmInstallScriptHandler::InstallScriptRunner;

cmInstallScriptHandler::cmInstallScriptHandler(
  std::string _binaryDir, std::vector<std::string> _components,
  std::string _config, std::vector<std::string>& args)
  : components(std::move(_components))
  , binaryDir(std::move(_binaryDir))
{
  if (this->components.empty()) {
    this->components.emplace_back(std::string{});
  }

  std::string const& file =
    cmStrCat(this->binaryDir, "/CMakeFiles/InstallScripts.json");
  this->parallel = false;

  auto addScript = [this, &args](std::string script, std::string component,
                                 std::string config) -> void {
    this->scripts.push_back({ script, config, args });
    if (!component.empty()) {
      this->scripts.back().command.insert(
        this->scripts.back().command.end() - 1,
        cmStrCat("-DCMAKE_INSTALL_COMPONENT=", component));
    }
    if (!config.empty()) {
      this->scripts.back().command.insert(
        this->scripts.back().command.end() - 1,
        cmStrCat("-DCMAKE_INSTALL_CONFIG_NAME=", config));
    }
    this->scripts.back().command.emplace_back(script);
    this->directories.push_back(cmSystemTools::GetFilenamePath(script));
  };

  int compare = 1;
  if (cmSystemTools::FileExists(file)) {
    cmSystemTools::FileTimeCompare(
      cmStrCat(this->binaryDir, "/CMakeFiles/cmake.check_cache"), file,
      &compare);
  }
  if (compare < 1) {
    Json::CharReaderBuilder rbuilder;
    auto JsonReader =
      std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
    std::vector<char> content;
    Json::Value value;
    cmJSONState state(file, &value);
    this->parallel = value["Parallel"].asBool();
    if (this->parallel) {
      args.insert(args.end() - 1, "-DCMAKE_INSTALL_LOCAL_ONLY=1");
    }
    if (_config.empty() && value.isMember("Configs")) {
      for (auto const& config : value["Configs"]) {
        this->configs.push_back(config.asCString());
      }
    } else {
      this->configs.push_back(_config);
    }
    for (auto const& script : value["InstallScripts"]) {
      for (auto const& component : components) {
        for (auto const& config : configs) {
          addScript(script.asCString(), component, config);
        }
      }
      if (!this->parallel) {
        break;
      }
    }
  } else {
    for (auto const& component : components) {
      addScript(cmStrCat(this->binaryDir, "/cmake_install.cmake"), component,
                _config);
    }
  }
}

bool cmInstallScriptHandler::IsParallel()
{
  return this->parallel;
}

std::vector<InstallScript> cmInstallScriptHandler::GetScripts() const
{
  return this->scripts;
}

int cmInstallScriptHandler::Install(unsigned int j,
                                    cmInstrumentation& instrumentation)
{
  cm::uv_loop_ptr loop;
  loop.init();
  std::vector<InstallScriptRunner> runners;
  runners.reserve(this->scripts.size());

  std::vector<std::string> instrument_arg;
  if (instrumentation.HasQuery()) {
    instrument_arg = { cmSystemTools::GetCTestCommand(),
                       "--instrument",
                       "--command-type",
                       "install",
                       "--build-dir",
                       this->binaryDir,
                       "--config",
                       "",
                       "--" };
  }

  for (auto& script : this->scripts) {
    if (!instrument_arg.empty()) {
      instrument_arg[7] = script.config; // --config <script.config>
    }
    script.command.insert(script.command.begin(), instrument_arg.begin(),
                          instrument_arg.end());
    runners.emplace_back(script);
  }
  std::size_t working = 0;
  std::size_t installed = 0;
  std::size_t i = 0;

  std::function<void()> queueScripts;
  queueScripts = [&runners, &working, &installed, &i, &loop, j,
                  &queueScripts]() {
    for (auto queue = std::min(j - working, runners.size() - i); queue > 0;
         --queue) {
      ++working;
      runners[i].start(loop,
                       [&runners, &working, &installed, i, &queueScripts]() {
                         runners[i].printResult(++installed, runners.size());
                         --working;
                         queueScripts();
                       });
      ++i;
    }
  };
  queueScripts();
  uv_run(loop, UV_RUN_DEFAULT);

  // Write install manifest
  std::string install_manifest;
  for (auto const& component : this->components) {
    if (component.empty()) {
      install_manifest = "install_manifest.txt";
    } else {
      cmsys::RegularExpression regEntry;
      if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") && regEntry.find(component)) {
        install_manifest = cmStrCat("install_manifest_", component, ".txt");
      } else {
        cmCryptoHash md5(cmCryptoHash::AlgoMD5);
        md5.Initialize();
        install_manifest =
          cmStrCat("install_manifest_", md5.HashString(component), ".txt");
      }
    }
    cmGeneratedFileStream fout(
      cmStrCat(this->binaryDir, '/', install_manifest));
    fout.SetCopyIfDifferent(true);
    for (auto const& dir : this->directories) {
      auto local_manifest = cmStrCat(dir, "/install_local_manifest.txt");
      if (cmSystemTools::FileExists(local_manifest)) {
        cmsys::ifstream fin(local_manifest.c_str());
        std::string line;
        while (std::getline(fin, line)) {
          fout << line << "\n";
        }
      }
    }
  }
  return 0;
}

InstallScriptRunner::InstallScriptRunner(InstallScript const& script)
{
  this->name = cmSystemTools::RelativePath(
    cmSystemTools::GetLogicalWorkingDirectory(), script.path);
  this->command = script.command;
}

void InstallScriptRunner::start(cm::uv_loop_ptr& loop,
                                std::function<void()> callback)
{
  cmUVProcessChainBuilder builder;
  builder.AddCommand(this->command)
    .SetExternalLoop(*loop)
    .SetMergedBuiltinStreams();
  this->chain = cm::make_unique<cmUVProcessChain>(builder.Start());
  this->streamHandler = cmUVStreamRead(
    this->chain->OutputStream(),
    [this](std::vector<char> data) {
      std::string strdata;
      cmProcessOutput(cmProcessOutput::Auto)
        .DecodeText(data.data(), data.size(), strdata);
      this->output.push_back(strdata);
    },
    std::move(callback));
}

void InstallScriptRunner::printResult(std::size_t n, std::size_t total)
{
  cmSystemTools::Stdout(cmStrCat('[', n, '/', total, "] ", this->name, '\n'));
  for (auto const& line : this->output) {
    cmSystemTools::Stdout(line);
  }
}
