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

#include "cmsys/FStream.hxx"

#include "cmAlgorithms.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmake.h"

#include <algorithm>

// -- Class methods

void cmQtAutoGenerator::Logger::SetVerbose(bool value)
{
  Verbose_ = value;
}

void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
{
  ColorOutput_ = value;
}

std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title)
{
  std::string head = title;
  head += '\n';
  head.append(head.size() - 1, '-');
  head += '\n';
  return head;
}

void cmQtAutoGenerator::Logger::Info(GeneratorT genType,
                                     std::string const& message)
{
  std::string msg = GeneratorName(genType);
  msg += ": ";
  msg += message;
  if (msg.back() != '\n') {
    msg.push_back('\n');
  }
  {
    std::lock_guard<std::mutex> lock(Mutex_);
    cmSystemTools::Stdout(msg.c_str(), msg.size());
  }
}

void cmQtAutoGenerator::Logger::Warning(GeneratorT genType,
                                        std::string const& message)
{
  std::string msg;
  if (message.find('\n') == std::string::npos) {
    // Single line message
    msg += GeneratorName(genType);
    msg += " warning: ";
  } else {
    // Multi line message
    msg += HeadLine(GeneratorName(genType) + " warning");
  }
  // Message
  msg += message;
  if (msg.back() != '\n') {
    msg.push_back('\n');
  }
  msg.push_back('\n');
  {
    std::lock_guard<std::mutex> lock(Mutex_);
    cmSystemTools::Stdout(msg.c_str(), msg.size());
  }
}

void cmQtAutoGenerator::Logger::WarningFile(GeneratorT genType,
                                            std::string const& filename,
                                            std::string const& message)
{
  std::string msg = "  ";
  msg += Quoted(filename);
  msg.push_back('\n');
  // Message
  msg += message;
  Warning(genType, msg);
}

void cmQtAutoGenerator::Logger::Error(GeneratorT genType,
                                      std::string const& message)
{
  std::string msg;
  msg += HeadLine(GeneratorName(genType) + " error");
  // Message
  msg += message;
  if (msg.back() != '\n') {
    msg.push_back('\n');
  }
  msg.push_back('\n');
  {
    std::lock_guard<std::mutex> lock(Mutex_);
    cmSystemTools::Stderr(msg.c_str(), msg.size());
  }
}

void cmQtAutoGenerator::Logger::ErrorFile(GeneratorT genType,
                                          std::string const& filename,
                                          std::string const& message)
{
  std::string emsg = "  ";
  emsg += Quoted(filename);
  emsg += '\n';
  // Message
  emsg += message;
  Error(genType, emsg);
}

void cmQtAutoGenerator::Logger::ErrorCommand(
  GeneratorT genType, std::string const& message,
  std::vector<std::string> const& command, std::string const& output)
{
  std::string msg;
  msg.push_back('\n');
  msg += HeadLine(GeneratorName(genType) + " subprocess error");
  msg += message;
  if (msg.back() != '\n') {
    msg.push_back('\n');
  }
  msg.push_back('\n');
  msg += HeadLine("Command");
  msg += QuotedCommand(command);
  if (msg.back() != '\n') {
    msg.push_back('\n');
  }
  msg.push_back('\n');
  msg += HeadLine("Output");
  msg += output;
  if (msg.back() != '\n') {
    msg.push_back('\n');
  }
  msg.push_back('\n');
  {
    std::lock_guard<std::mutex> lock(Mutex_);
    cmSystemTools::Stderr(msg.c_str(), msg.size());
  }
}

std::string cmQtAutoGenerator::FileSystem::GetRealPath(
  std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::GetRealPath(filename);
}

std::string cmQtAutoGenerator::FileSystem::CollapseCombinedPath(
  std::string const& dir, std::string const& file)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::CollapseCombinedPath(dir, file);
}

void cmQtAutoGenerator::FileSystem::SplitPath(
  const std::string& p, std::vector<std::string>& components,
  bool expand_home_dir)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  cmSystemTools::SplitPath(p, components, expand_home_dir);
}

std::string cmQtAutoGenerator::FileSystem::JoinPath(
  const std::vector<std::string>& components)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::JoinPath(components);
}

std::string cmQtAutoGenerator::FileSystem::JoinPath(
  std::vector<std::string>::const_iterator first,
  std::vector<std::string>::const_iterator last)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::JoinPath(first, last);
}

std::string cmQtAutoGenerator::FileSystem::GetFilenameWithoutLastExtension(
  const std::string& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::GetFilenameWithoutLastExtension(filename);
}

std::string cmQtAutoGenerator::FileSystem::SubDirPrefix(
  std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmQtAutoGen::SubDirPrefix(filename);
}

void cmQtAutoGenerator::FileSystem::setupFilePathChecksum(
  std::string const& currentSrcDir, std::string const& currentBinDir,
  std::string const& projectSrcDir, std::string const& projectBinDir)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  FilePathChecksum_.setupParentDirs(currentSrcDir, currentBinDir,
                                    projectSrcDir, projectBinDir);
}

std::string cmQtAutoGenerator::FileSystem::GetFilePathChecksum(
  std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return FilePathChecksum_.getPart(filename);
}

bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::FileExists(filename);
}

bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename,
                                               bool isFile)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::FileExists(filename, isFile);
}

unsigned long cmQtAutoGenerator::FileSystem::FileLength(
  std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::FileLength(filename);
}

bool cmQtAutoGenerator::FileSystem::FileIsOlderThan(
  std::string const& buildFile, std::string const& sourceFile,
  std::string* error)
{
  bool res(false);
  int result = 0;
  {
    std::lock_guard<std::mutex> lock(Mutex_);
    res = cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result);
  }
  if (res) {
    res = (result < 0);
  } else {
    if (error != nullptr) {
      error->append(
        "File modification time comparison failed for the files\n  ");
      error->append(Quoted(buildFile));
      error->append("\nand\n  ");
      error->append(Quoted(sourceFile));
    }
  }
  return res;
}

bool cmQtAutoGenerator::FileSystem::FileRead(std::string& content,
                                             std::string const& filename,
                                             std::string* error)
{
  bool success = false;
  if (FileExists(filename, true)) {
    unsigned long const length = FileLength(filename);
    {
      std::lock_guard<std::mutex> lock(Mutex_);
      cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
      if (ifs) {
        content.reserve(length);
        content.assign(std::istreambuf_iterator<char>{ ifs },
                       std::istreambuf_iterator<char>{});
        if (ifs) {
          success = true;
        } else {
          content.clear();
          if (error != nullptr) {
            error->append("Reading from the file failed.");
          }
        }
      } else if (error != nullptr) {
        error->append("Opening the file for reading failed.");
      }
    }
  } else if (error != nullptr) {
    error->append(
      "The file does not exist, is not readable or is a directory.");
  }
  return success;
}

bool cmQtAutoGenerator::FileSystem::FileRead(GeneratorT genType,
                                             std::string& content,
                                             std::string const& filename)
{
  std::string error;
  if (!FileRead(content, filename, &error)) {
    Log()->ErrorFile(genType, filename, error);
    return false;
  }
  return true;
}

bool cmQtAutoGenerator::FileSystem::FileWrite(std::string const& filename,
                                              std::string const& content,
                                              std::string* error)
{
  bool success = false;
  // Make sure the parent directory exists
  if (MakeParentDirectory(filename)) {
    std::lock_guard<std::mutex> lock(Mutex_);
    cmsys::ofstream outfile;
    outfile.open(filename.c_str(),
                 (std::ios::out | std::ios::binary | std::ios::trunc));
    if (outfile) {
      outfile << content;
      // Check for write errors
      if (outfile.good()) {
        success = true;
      } else {
        if (error != nullptr) {
          error->assign("File writing failed");
        }
      }
    } else {
      if (error != nullptr) {
        error->assign("Opening file for writing failed");
      }
    }
  } else {
    if (error != nullptr) {
      error->assign("Could not create parent directory");
    }
  }
  return success;
}

bool cmQtAutoGenerator::FileSystem::FileWrite(GeneratorT genType,
                                              std::string const& filename,
                                              std::string const& content)
{
  std::string error;
  if (!FileWrite(filename, content, &error)) {
    Log()->ErrorFile(genType, filename, error);
    return false;
  }
  return true;
}

bool cmQtAutoGenerator::FileSystem::FileDiffers(std::string const& filename,
                                                std::string const& content)
{
  bool differs = true;
  {
    std::string oldContents;
    if (FileRead(oldContents, filename)) {
      differs = (oldContents != content);
    }
  }
  return differs;
}

bool cmQtAutoGenerator::FileSystem::FileRemove(std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::RemoveFile(filename);
}

bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::Touch(filename, false);
}

bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)
{
  std::lock_guard<std::mutex> lock(Mutex_);
  return cmSystemTools::MakeDirectory(dirname);
}

bool cmQtAutoGenerator::FileSystem::MakeDirectory(GeneratorT genType,
                                                  std::string const& dirname)
{
  if (!MakeDirectory(dirname)) {
    Log()->ErrorFile(genType, dirname, "Could not create directory");
    return false;
  }
  return true;
}

bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
  std::string const& filename)
{
  bool success = true;
  std::string const dirName = cmSystemTools::GetFilenamePath(filename);
  if (!dirName.empty()) {
    success = MakeDirectory(dirName);
  }
  return success;
}

bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
  GeneratorT genType, std::string const& filename)
{
  if (!MakeParentDirectory(filename)) {
    Log()->ErrorFile(genType, filename, "Could not create parent directory");
    return false;
  }
  return true;
}

int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::init(uv_loop_t* uv_loop,
                                                     ReadOnlyProcessT* process)
{
  Process_ = process;
  Target_ = nullptr;
  return UVPipe_.init(*uv_loop, 0, this);
}

int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::startRead(std::string* target)
{
  Target_ = target;
  return uv_read_start(uv_stream(), &PipeT::UVAlloc, &PipeT::UVData);
}

void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::reset()
{
  Process_ = nullptr;
  Target_ = nullptr;
  UVPipe_.reset();
  Buffer_.clear();
  Buffer_.shrink_to_fit();
}

void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVAlloc(uv_handle_t* handle,
                                                         size_t suggestedSize,
                                                         uv_buf_t* buf)
{
  auto& pipe = *reinterpret_cast<PipeT*>(handle->data);
  pipe.Buffer_.resize(suggestedSize);
  buf->base = &pipe.Buffer_.front();
  buf->len = pipe.Buffer_.size();
}

void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVData(uv_stream_t* stream,
                                                        ssize_t nread,
                                                        const uv_buf_t* buf)
{
  auto& pipe = *reinterpret_cast<PipeT*>(stream->data);
  if (nread > 0) {
    // Append data to merged output
    if ((buf->base != nullptr) && (pipe.Target_ != nullptr)) {
      pipe.Target_->append(buf->base, nread);
    }
  } else if (nread < 0) {
    // EOF or error
    auto* proc = pipe.Process_;
    // Check it this an unusual error
    if (nread != UV_EOF) {
      if (!proc->Result()->error()) {
        proc->Result()->ErrorMessage =
          "libuv reading from pipe failed with error code ";
        proc->Result()->ErrorMessage += std::to_string(nread);
      }
    }
    // Clear libuv pipe handle and try to finish
    pipe.reset();
    proc->UVTryFinish();
  }
}

void cmQtAutoGenerator::ProcessResultT::reset()
{
  ExitStatus = 0;
  TermSignal = 0;
  if (!StdOut.empty()) {
    StdOut.clear();
    StdOut.shrink_to_fit();
  }
  if (!StdErr.empty()) {
    StdErr.clear();
    StdErr.shrink_to_fit();
  }
  if (!ErrorMessage.empty()) {
    ErrorMessage.clear();
    ErrorMessage.shrink_to_fit();
  }
}

void cmQtAutoGenerator::ReadOnlyProcessT::setup(
  ProcessResultT* result, bool mergedOutput,
  std::vector<std::string> const& command, std::string const& workingDirectory)
{
  Setup_.WorkingDirectory = workingDirectory;
  Setup_.Command = command;
  Setup_.Result = result;
  Setup_.MergedOutput = mergedOutput;
}

bool cmQtAutoGenerator::ReadOnlyProcessT::start(
  uv_loop_t* uv_loop, std::function<void()>&& finishedCallback)
{
  if (IsStarted() || (Result() == nullptr)) {
    return false;
  }

  // Reset result before the start
  Result()->reset();

  // Fill command string pointers
  if (!Setup().Command.empty()) {
    CommandPtr_.reserve(Setup().Command.size() + 1);
    for (std::string const& arg : Setup().Command) {
      CommandPtr_.push_back(arg.c_str());
    }
    CommandPtr_.push_back(nullptr);
  } else {
    Result()->ErrorMessage = "Empty command";
  }

  if (!Result()->error()) {
    if (UVPipeOut_.init(uv_loop, this) != 0) {
      Result()->ErrorMessage = "libuv stdout pipe initialization failed";
    }
  }
  if (!Result()->error()) {
    if (UVPipeErr_.init(uv_loop, this) != 0) {
      Result()->ErrorMessage = "libuv stderr pipe initialization failed";
    }
  }
  if (!Result()->error()) {
    // -- Setup process stdio options
    // stdin
    UVOptionsStdIO_[0].flags = UV_IGNORE;
    UVOptionsStdIO_[0].data.stream = nullptr;
    // stdout
    UVOptionsStdIO_[1].flags =
      static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
    // stderr
    UVOptionsStdIO_[2].flags =
      static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();

    // -- Setup process options
    std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
    UVOptions_.exit_cb = &ReadOnlyProcessT::UVExit;
    UVOptions_.file = CommandPtr_[0];
    UVOptions_.args = const_cast<char**>(&CommandPtr_.front());
    UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
    UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
    UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
    UVOptions_.stdio = &UVOptionsStdIO_.front();

    // -- Spawn process
    if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
      Result()->ErrorMessage = "libuv process spawn failed";
    }
  }
  // -- Start reading from stdio streams
  if (!Result()->error()) {
    if (UVPipeOut_.startRead(&Result()->StdOut) != 0) {
      Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
    }
  }
  if (!Result()->error()) {
    if (UVPipeErr_.startRead(Setup_.MergedOutput ? &Result()->StdOut
                                                 : &Result()->StdErr) != 0) {
      Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
    }
  }

  if (!Result()->error()) {
    IsStarted_ = true;
    FinishedCallback_ = std::move(finishedCallback);
  } else {
    // Clear libuv handles and finish
    UVProcess_.reset();
    UVPipeOut_.reset();
    UVPipeErr_.reset();
    CommandPtr_.clear();
  }

  return IsStarted();
}

void cmQtAutoGenerator::ReadOnlyProcessT::UVExit(uv_process_t* handle,
                                                 int64_t exitStatus,
                                                 int termSignal)
{
  auto& proc = *reinterpret_cast<ReadOnlyProcessT*>(handle->data);
  if (proc.IsStarted() && !proc.IsFinished()) {
    // Set error message on demand
    proc.Result()->ExitStatus = exitStatus;
    proc.Result()->TermSignal = termSignal;
    if (!proc.Result()->error()) {
      if (termSignal != 0) {
        proc.Result()->ErrorMessage = "Process was terminated by signal ";
        proc.Result()->ErrorMessage +=
          std::to_string(proc.Result()->TermSignal);
      } else if (exitStatus != 0) {
        proc.Result()->ErrorMessage = "Process failed with return value ";
        proc.Result()->ErrorMessage +=
          std::to_string(proc.Result()->ExitStatus);
      }
    }

    // Reset process handle and try to finish
    proc.UVProcess_.reset();
    proc.UVTryFinish();
  }
}

void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish()
{
  // There still might be data in the pipes after the process has finished.
  // Therefore check if the process is finished AND all pipes are closed
  // before signaling the worker thread to continue.
  if (UVProcess_.get() == nullptr) {
    if (UVPipeOut_.uv_pipe() == nullptr) {
      if (UVPipeErr_.uv_pipe() == nullptr) {
        IsFinished_ = true;
        FinishedCallback_();
      }
    }
  }
}

cmQtAutoGenerator::cmQtAutoGenerator()
  : FileSys_(&Logger_)
{
  // Initialize logger
  Logger_.SetVerbose(cmSystemTools::HasEnv("VERBOSE"));
  {
    std::string colorEnv;
    cmSystemTools::GetEnv("COLOR", colorEnv);
    if (!colorEnv.empty()) {
      Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv.c_str()));
    } else {
      Logger_.SetColorOutput(true);
    }
  }

  // Initialize libuv loop
  uv_disable_stdio_inheritance();
#ifdef CMAKE_UV_SIGNAL_HACK
  UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>();
#endif
  UVLoop_ = cm::make_unique<uv_loop_t>();
  uv_loop_init(UVLoop());
}

cmQtAutoGenerator::~cmQtAutoGenerator()
{
  // Close libuv loop
  uv_loop_close(UVLoop());
}

bool cmQtAutoGenerator::Run(std::string const& infoFile,
                            std::string const& config)
{
  // Info settings
  InfoFile_ = infoFile;
  cmSystemTools::ConvertToUnixSlashes(InfoFile_);
  InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
  InfoConfig_ = config;

  bool success = false;
  {
    cmake cm(cmake::RoleScript);
    cm.SetHomeOutputDirectory(InfoDir());
    cm.SetHomeDirectory(InfoDir());
    cm.GetCurrentSnapshot().SetDefaultDefinitions();
    cmGlobalGenerator gg(&cm);

    cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
    snapshot.GetDirectory().SetCurrentBinary(InfoDir());
    snapshot.GetDirectory().SetCurrentSource(InfoDir());

    auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
    // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
    // https://gitlab.kitware.com/cmake/cmake/issues/17570
    makefile->SetPolicyVersion("3.9");
    gg.SetCurrentMakefile(makefile.get());
    success = this->Init(makefile.get());
  }
  if (success) {
    success = this->Process();
  }
  return success;
}

std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
                                            const char* key)
{
  std::string prefix(key);
  prefix += ':';
  std::string::size_type pos = content.find(prefix);
  if (pos != std::string::npos) {
    pos += prefix.size();
    if (pos < content.size()) {
      std::string::size_type posE = content.find('\n', pos);
      if ((posE != std::string::npos) && (posE != pos)) {
        return content.substr(pos, posE - pos);
      }
    }
  }
  return std::string();
}
