/* 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 "cmInstrumentationInterrupt.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 installConfig, 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));
  };

  // Trust the parallel install index unless the cache marker is newer.  Both
  // files are written back-to-back while generating this build tree, so any
  // ordering between them lives in a sub-second window that some filesystems
  // (e.g. NFS on AIX) do not resolve by write time.  Compare at whole-second
  // resolution: a genuinely stale index left by an older CMake reconfigure is
  // always at least a configure run (seconds) older, while the sub-second
  // jitter of a single generate step is ignored.
  bool indexIsFresh = false;
  if (cmSystemTools::FileExists(file)) {
    long int const cacheTime = cmSystemTools::ModifiedTime(
      cmStrCat(this->BinaryDir, "/CMakeFiles/cmake.check_cache"));
    indexIsFresh = cacheTime <= cmSystemTools::ModifiedTime(file);
  }
  if (indexIsFresh) {
    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 (installConfig.empty() && value.isMember("Configs")) {
      for (auto const& config : value["Configs"]) {
        this->Configs.push_back(config.asCString());
      }
    } else {
      this->Configs.push_back(installConfig);
    }
    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,
                installConfig);
    }
  }
}

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> instrumentArg;
  if (instrumentation.HasQuery()) {
    instrumentArg = { cmSystemTools::GetCTestCommand(),
                      "--instrument",
                      "--command-type",
                      "install",
                      "--build-dir",
                      this->BinaryDir,
                      "--config",
                      "",
                      "--" };
  }

  for (auto& script : this->Scripts) {
    if (!instrumentArg.empty()) {
      instrumentArg[7] = script.config; // --config <script.config>
    }
    script.command.insert(script.command.begin(), instrumentArg.begin(),
                          instrumentArg.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]() {
    if (cmInstrumentationInterrupt::PendingInterruptSignal() != 0) {
      // Interrupted (e.g. Ctrl+C): launch no further scripts.  In-flight
      // children share the process group, receive the signal, and exit on
      // their own, draining the event loop; queueScripts is the single
      // re-entry point for launching, so guarding it here stops all remaining
      // work without killing anything.
      return;
    }
    for (auto queue = std::min(j - working, runners.size() - i); queue > 0;
         --queue) {
      ++working;
      bool started = runners[i].start(
        loop, [&runners, &working, &installed, i, &queueScripts]() {
          runners[i].printResult(++installed, runners.size());
          --working;
          queueScripts();
        });
      if (!started) {
        // The child could not be spawned.  Release its scheduling slot so the
        // remaining scripts still run; it is counted as a failure after the
        // event loop completes.
        --working;
      }
      ++i;
    }
  };
  queueScripts();
  uv_run(loop, UV_RUN_DEFAULT);

  // Aggregate child results.  When an interrupt stopped queueScripts, the
  // runners beyond the dispatched prefix [0, i) were never started (they have
  // a null process handle); those are "not run", not "failed", so exclude
  // them.  With no interrupt every runner was dispatched and this inspects
  // them all, matching the non-interrupt behavior exactly.
  std::size_t const inspect =
    cmInstrumentationInterrupt::PendingInterruptSignal() != 0 ? i
                                                              : runners.size();
  int result = 0;
  for (std::size_t k = 0; k < inspect; ++k) {
    if (runners[k].Failed()) {
      runners[k].printFailure();
      result = 1;
    }
  }

  // Write the install manifest only when every script succeeded.  A failed
  // install must not leave behind a manifest that looks complete.
  if (result == 0) {
    std::string installManifest;
    for (auto const& component : this->Components) {
      if (component.empty()) {
        installManifest = "install_manifest.txt";
      } else {
        cmsys::RegularExpression regEntry;
        if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") &&
            regEntry.find(component)) {
          installManifest = cmStrCat("install_manifest_", component, ".txt");
        } else {
          cmCryptoHash md5(cmCryptoHash::AlgoMD5);
          md5.Initialize();
          installManifest =
            cmStrCat("install_manifest_", md5.HashString(component), ".txt");
        }
      }
      cmGeneratedFileStream fout(
        cmStrCat(this->BinaryDir, '/', installManifest));
      fout.SetCopyIfDifferent(true);
      for (auto const& dir : this->Directories) {
        auto localManifest = cmStrCat(dir, "/install_local_manifest.txt");
        if (cmSystemTools::FileExists(localManifest)) {
          cmsys::ifstream fin(localManifest.c_str());
          std::string line;
          while (std::getline(fin, line)) {
            fout << line << "\n";
          }
        }
      }
    }
  }
  return result;
}

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

bool 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());
  if (!this->Chain->Valid()) {
    return false;
  }
  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));
  return true;
}

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);
  }
}

bool InstallScriptRunner::Failed() const
{
  if (!this->Chain || !this->Chain->Valid()) {
    return true;
  }
  auto const& status = this->Chain->GetStatus(0);
  return status.SpawnResult != 0 || status.TermSignal != 0 ||
    status.ExitStatus != 0;
}

void InstallScriptRunner::printFailure()
{
  std::string detail;
  if (!this->Chain || !this->Chain->Valid()) {
    // The chain never spawned a process (e.g. pipe/loop setup failed).
    detail = "failed to start";
  } else {
    auto const& status = this->Chain->GetStatus(0);
    auto exception = status.GetException();
    switch (exception.first) {
      case cmUVProcessChain::ExceptionCode::None:
        detail = cmStrCat("exited with code ", status.ExitStatus);
        break;
      case cmUVProcessChain::ExceptionCode::Spawn:
        // Prepared, but the process could not be executed.
        detail = cmStrCat("failed to start: ", exception.second);
        break;
      default:
        detail = exception.second;
        break;
    }
  }
  cmSystemTools::Stderr(
    cmStrCat("CMake Error: install script '", this->Name, "' ", detail, '\n'));
}
