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

#include <cassert>
#include <istream> // IWYU pragma: keep
#include <iterator>
#include <utility>

#include <cm/memory>

#include <cm3p/uv.h>

#include "cmGetPipes.h"
#include "cmUVHandlePtr.h"
#include "cmUVStreambuf.h"

struct cmUVProcessChain::InternalData
{
  struct BasicStreamData
  {
    cmUVStreambuf Streambuf;
    cm::uv_pipe_ptr BuiltinStream;
    uv_stdio_container_t Stdio;
  };

  template <typename IOStream>
  struct StreamData : public BasicStreamData
  {
    StreamData()
      : BuiltinIOStream(&this->Streambuf)
    {
    }

    IOStream BuiltinIOStream;

    IOStream* GetBuiltinStream()
    {
      if (this->BuiltinStream.get()) {
        return &this->BuiltinIOStream;
      }
      return nullptr;
    }
  };

  struct ProcessData
  {
    cmUVProcessChain::InternalData* Data;
    cm::uv_process_ptr Process;
    cm::uv_pipe_ptr OutputPipe;
    bool Finished = false;
    Status ProcessStatus;
  };

  const cmUVProcessChainBuilder* Builder = nullptr;

  bool Valid = false;

  cm::uv_loop_ptr Loop;

  StreamData<std::istream> OutputStreamData;
  StreamData<std::istream> ErrorStreamData;

  unsigned int ProcessesCompleted = 0;
  std::vector<std::unique_ptr<ProcessData>> Processes;

  bool Prepare(const cmUVProcessChainBuilder* builder);
  bool AddCommand(const cmUVProcessChainBuilder::ProcessConfiguration& config,
                  bool first, bool last);
  bool Finish();

  static const Status* GetStatus(const ProcessData& data);
};

cmUVProcessChainBuilder::cmUVProcessChainBuilder()
{
  this->SetNoStream(Stream_INPUT)
    .SetNoStream(Stream_OUTPUT)
    .SetNoStream(Stream_ERROR);
}

cmUVProcessChainBuilder& cmUVProcessChainBuilder::AddCommand(
  const std::vector<std::string>& arguments)
{
  if (!arguments.empty()) {
    this->Processes.emplace_back();
    this->Processes.back().Arguments = arguments;
  }
  return *this;
}

cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetNoStream(Stream stdio)
{
  switch (stdio) {
    case Stream_INPUT:
    case Stream_OUTPUT:
    case Stream_ERROR: {
      auto& streamData = this->Stdio[stdio];
      streamData.Type = None;
      break;
    }
  }
  return *this;
}

cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetBuiltinStream(
  Stream stdio)
{
  switch (stdio) {
    case Stream_INPUT:
      // FIXME
      break;

    case Stream_OUTPUT:
    case Stream_ERROR: {
      auto& streamData = this->Stdio[stdio];
      streamData.Type = Builtin;
      break;
    }
  }
  return *this;
}

cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
  Stream stdio, int fd)
{
  switch (stdio) {
    case Stream_INPUT:
      // FIXME
      break;

    case Stream_OUTPUT:
    case Stream_ERROR: {
      auto& streamData = this->Stdio[stdio];
      streamData.Type = External;
      streamData.FileDescriptor = fd;
      break;
    }
  }
  return *this;
}

cmUVProcessChain cmUVProcessChainBuilder::Start() const
{
  cmUVProcessChain chain;

  if (!chain.Data->Prepare(this)) {
    return chain;
  }

  for (auto it = this->Processes.begin(); it != this->Processes.end(); ++it) {
    if (!chain.Data->AddCommand(*it, it == this->Processes.begin(),
                                it == std::prev(this->Processes.end()))) {
      return chain;
    }
  }

  chain.Data->Finish();

  return chain;
}

const cmUVProcessChain::Status* cmUVProcessChain::InternalData::GetStatus(
  const cmUVProcessChain::InternalData::ProcessData& data)
{
  if (data.Finished) {
    return &data.ProcessStatus;
  }
  return nullptr;
}

bool cmUVProcessChain::InternalData::Prepare(
  const cmUVProcessChainBuilder* builder)
{
  this->Builder = builder;

  auto const& output =
    this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT];
  auto& outputData = this->OutputStreamData;
  switch (output.Type) {
    case cmUVProcessChainBuilder::None:
      outputData.Stdio.flags = UV_IGNORE;
      break;

    case cmUVProcessChainBuilder::Builtin:
      outputData.BuiltinStream.init(*this->Loop, 0);
      outputData.Stdio.flags =
        static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
      outputData.Stdio.data.stream = outputData.BuiltinStream;
      break;

    case cmUVProcessChainBuilder::External:
      outputData.Stdio.flags = UV_INHERIT_FD;
      outputData.Stdio.data.fd = output.FileDescriptor;
      break;
  }

  auto const& error =
    this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR];
  auto& errorData = this->ErrorStreamData;
  switch (error.Type) {
    case cmUVProcessChainBuilder::None:
      errorData.Stdio.flags = UV_IGNORE;
      break;

    case cmUVProcessChainBuilder::Builtin: {
      int pipeFd[2];
      if (cmGetPipes(pipeFd) < 0) {
        return false;
      }

      errorData.BuiltinStream.init(*this->Loop, 0);
      if (uv_pipe_open(errorData.BuiltinStream, pipeFd[0]) < 0) {
        return false;
      }
      errorData.Stdio.flags = UV_INHERIT_FD;
      errorData.Stdio.data.fd = pipeFd[1];
      break;
    }

    case cmUVProcessChainBuilder::External:
      errorData.Stdio.flags = UV_INHERIT_FD;
      errorData.Stdio.data.fd = error.FileDescriptor;
      break;
  }

  return true;
}

bool cmUVProcessChain::InternalData::AddCommand(
  const cmUVProcessChainBuilder::ProcessConfiguration& config, bool first,
  bool last)
{
  this->Processes.emplace_back(cm::make_unique<ProcessData>());
  auto& process = *this->Processes.back();
  process.Data = this;

  auto options = uv_process_options_t();

  // Bounds were checked at add time, first element is guaranteed to exist
  options.file = config.Arguments[0].c_str();

  std::vector<const char*> arguments;
  for (auto const& arg : config.Arguments) {
    arguments.push_back(arg.c_str());
  }
  arguments.push_back(nullptr);
  options.args = const_cast<char**>(arguments.data());
  options.flags = UV_PROCESS_WINDOWS_HIDE;

  std::array<uv_stdio_container_t, 3> stdio;
  stdio[0] = uv_stdio_container_t();
  if (first) {
    stdio[0].flags = UV_IGNORE;
  } else {
    assert(this->Processes.size() >= 2);
    auto& prev = *this->Processes[this->Processes.size() - 2];
    stdio[0].flags = UV_INHERIT_STREAM;
    stdio[0].data.stream = prev.OutputPipe;
  }
  if (last) {
    stdio[1] = this->OutputStreamData.Stdio;
  } else {
    if (process.OutputPipe.init(*this->Loop, 0) < 0) {
      return false;
    }
    stdio[1] = uv_stdio_container_t();
    stdio[1].flags =
      static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    stdio[1].data.stream = process.OutputPipe;
  }
  stdio[2] = this->ErrorStreamData.Stdio;

  options.stdio = stdio.data();
  options.stdio_count = 3;
  options.exit_cb = [](uv_process_t* handle, int64_t exitStatus,
                       int termSignal) {
    auto* processData = static_cast<ProcessData*>(handle->data);
    processData->Finished = true;
    processData->ProcessStatus.ExitStatus = exitStatus;
    processData->ProcessStatus.TermSignal = termSignal;
    processData->Data->ProcessesCompleted++;
  };

  return process.Process.spawn(*this->Loop, options, &process) >= 0;
}

bool cmUVProcessChain::InternalData::Finish()
{
  if (this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT].Type ==
      cmUVProcessChainBuilder::Builtin) {
    this->OutputStreamData.Streambuf.open(
      this->OutputStreamData.BuiltinStream);
  }

  if (this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR].Type ==
      cmUVProcessChainBuilder::Builtin) {
    cm::uv_pipe_ptr tmpPipe;
    if (tmpPipe.init(*this->Loop, 0) < 0) {
      return false;
    }
    if (uv_pipe_open(tmpPipe, this->ErrorStreamData.Stdio.data.fd) < 0) {
      return false;
    }
    tmpPipe.reset();

    this->ErrorStreamData.Streambuf.open(this->ErrorStreamData.BuiltinStream);
  }

  this->Valid = true;
  return true;
}

cmUVProcessChain::cmUVProcessChain()
  : Data(cm::make_unique<InternalData>())
{
  this->Data->Loop.init();
}

cmUVProcessChain::cmUVProcessChain(cmUVProcessChain&& other) noexcept
  : Data(std::move(other.Data))
{
}

cmUVProcessChain::~cmUVProcessChain() = default;

cmUVProcessChain& cmUVProcessChain::operator=(
  cmUVProcessChain&& other) noexcept
{
  this->Data = std::move(other.Data);
  return *this;
}

uv_loop_t& cmUVProcessChain::GetLoop()
{
  return *this->Data->Loop;
}

std::istream* cmUVProcessChain::OutputStream()
{
  return this->Data->OutputStreamData.GetBuiltinStream();
}

std::istream* cmUVProcessChain::ErrorStream()
{
  return this->Data->ErrorStreamData.GetBuiltinStream();
}

bool cmUVProcessChain::Valid() const
{
  return this->Data->Valid;
}

bool cmUVProcessChain::Wait(int64_t milliseconds)
{
  bool timeout = false;
  cm::uv_timer_ptr timer;

  if (milliseconds >= 0) {
    timer.init(*this->Data->Loop, &timeout);
    timer.start(
      [](uv_timer_t* handle) {
        auto* timeoutPtr = static_cast<bool*>(handle->data);
        *timeoutPtr = true;
      },
      milliseconds, 0);
  }

  while (!timeout &&
         this->Data->ProcessesCompleted < this->Data->Processes.size()) {
    uv_run(this->Data->Loop, UV_RUN_ONCE);
  }

  return !timeout;
}

std::vector<const cmUVProcessChain::Status*> cmUVProcessChain::GetStatus()
  const
{
  std::vector<const cmUVProcessChain::Status*> statuses(
    this->Data->Processes.size(), nullptr);
  for (std::size_t i = 0; i < statuses.size(); i++) {
    statuses[i] = this->GetStatus(i);
  }
  return statuses;
}

const cmUVProcessChain::Status* cmUVProcessChain::GetStatus(
  std::size_t index) const
{
  auto const& process = *this->Data->Processes[index];
  if (process.Finished) {
    return &process.ProcessStatus;
  }
  return nullptr;
}
