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

#include "cmServerDictionary.h"

#include "cmFileMonitor.h"
#include "cmServer.h"

#include <assert.h>

namespace {

struct write_req_t
{
  uv_write_t req;
  uv_buf_t buf;
};

void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
  (void)(handle);
  char* rawBuffer = new char[suggested_size];
  *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
}

void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
  auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
  if (nread >= 0) {
    conn->ReadData(std::string(buf->base, buf->base + nread));
  } else {
    conn->TriggerShutdown();
  }

  delete[](buf->base);
}

void on_write(uv_write_t* req, int status)
{
  (void)(status);
  auto conn = reinterpret_cast<cmServerConnection*>(req->data);

  // Free req and buffer
  write_req_t* wr = reinterpret_cast<write_req_t*>(req);
  delete[](wr->buf.base);
  delete wr;

  conn->ProcessNextRequest();
}

void on_new_connection(uv_stream_t* stream, int status)
{
  (void)(status);
  auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
  conn->Connect(stream);
}

void on_signal(uv_signal_t* signal, int signum)
{
  auto conn = reinterpret_cast<cmServerConnection*>(signal->data);
  (void)(signum);
  conn->TriggerShutdown();
}

void on_signal_close(uv_handle_t* handle)
{
  delete reinterpret_cast<uv_signal_t*>(handle);
}

void on_pipe_close(uv_handle_t* handle)
{
  delete reinterpret_cast<uv_pipe_t*>(handle);
}

void on_tty_close(uv_handle_t* handle)
{
  delete reinterpret_cast<uv_tty_t*>(handle);
}

} // namespace

class LoopGuard
{
public:
  LoopGuard(cmServerConnection* connection)
    : Connection(connection)
  {
    this->Connection->mLoop = uv_default_loop();
    if (!this->Connection->mLoop) {
      return;
    }
    this->Connection->mFileMonitor =
      new cmFileMonitor(this->Connection->mLoop);
  }

  ~LoopGuard()
  {
    if (!this->Connection->mLoop) {
      return;
    }

    if (this->Connection->mFileMonitor) {
      delete this->Connection->mFileMonitor;
    }
    uv_loop_close(this->Connection->mLoop);
    this->Connection->mLoop = nullptr;
  }

private:
  cmServerConnection* Connection;
};

cmServerConnection::cmServerConnection()
{
}

cmServerConnection::~cmServerConnection()
{
}

void cmServerConnection::SetServer(cmServer* s)
{
  this->Server = s;
}

bool cmServerConnection::ProcessEvents(std::string* errorMessage)
{
  assert(this->Server);
  errorMessage->clear();

  this->RawReadBuffer.clear();
  this->RequestBuffer.clear();

  LoopGuard guard(this);
  (void)(guard);
  if (!this->mLoop) {
    *errorMessage = "Internal Error: Failed to create event loop.";
    return false;
  }

  this->SIGINTHandler = new uv_signal_t;
  uv_signal_init(this->mLoop, this->SIGINTHandler);
  this->SIGINTHandler->data = static_cast<void*>(this);
  uv_signal_start(this->SIGINTHandler, &on_signal, SIGINT);

  this->SIGHUPHandler = new uv_signal_t;
  uv_signal_init(this->mLoop, this->SIGHUPHandler);
  this->SIGHUPHandler->data = static_cast<void*>(this);
  uv_signal_start(this->SIGHUPHandler, &on_signal, SIGHUP);

  if (!DoSetup(errorMessage)) {
    return false;
  }

  if (uv_run(this->mLoop, UV_RUN_DEFAULT) != 0) {
    *errorMessage = "Internal Error: Event loop stopped in unclean state.";
    return false;
  }

  // These need to be cleaned up by now:
  assert(!this->ReadStream);
  assert(!this->WriteStream);

  this->RawReadBuffer.clear();
  this->RequestBuffer.clear();

  return true;
}

void cmServerConnection::ReadData(const std::string& data)
{
  this->RawReadBuffer += data;

  for (;;) {
    auto needle = this->RawReadBuffer.find('\n');

    if (needle == std::string::npos) {
      return;
    }
    std::string line = this->RawReadBuffer.substr(0, needle);
    const auto ls = line.size();
    if (ls > 1 && line.at(ls - 1) == '\r') {
      line.erase(ls - 1, 1);
    }
    this->RawReadBuffer.erase(this->RawReadBuffer.begin(),
                              this->RawReadBuffer.begin() +
                                static_cast<long>(needle) + 1);
    if (line == kSTART_MAGIC) {
      this->RequestBuffer.clear();
      continue;
    }
    if (line == kEND_MAGIC) {
      this->Server->QueueRequest(this->RequestBuffer);
      this->RequestBuffer.clear();
    } else {
      this->RequestBuffer += line;
      this->RequestBuffer += "\n";
    }
  }
}

void cmServerConnection::TriggerShutdown()
{
  this->FileMonitor()->StopMonitoring();

  uv_signal_stop(this->SIGINTHandler);
  uv_signal_stop(this->SIGHUPHandler);

  uv_close(reinterpret_cast<uv_handle_t*>(this->SIGINTHandler),
           &on_signal_close); // delete handle
  uv_close(reinterpret_cast<uv_handle_t*>(this->SIGHUPHandler),
           &on_signal_close); // delete handle

  this->SIGINTHandler = nullptr;
  this->SIGHUPHandler = nullptr;

  this->TearDown();
}

void cmServerConnection::WriteData(const std::string& data)
{
  assert(this->WriteStream);

  auto ds = data.size();

  write_req_t* req = new write_req_t;
  req->req.data = this;
  req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds));
  memcpy(req->buf.base, data.c_str(), ds);

  uv_write(reinterpret_cast<uv_write_t*>(req),
           static_cast<uv_stream_t*>(this->WriteStream), &req->buf, 1,
           on_write);
}

void cmServerConnection::ProcessNextRequest()
{
  Server->PopOne();
}

void cmServerConnection::SendGreetings()
{
  Server->PrintHello();
}

cmServerStdIoConnection::cmServerStdIoConnection()
{
  this->Input.tty = nullptr;
  this->Output.tty = nullptr;
}

bool cmServerStdIoConnection::DoSetup(std::string* errorMessage)
{
  (void)(errorMessage);

  if (uv_guess_handle(1) == UV_TTY) {
    usesTty = true;
    this->Input.tty = new uv_tty_t;
    uv_tty_init(this->Loop(), this->Input.tty, 0, 1);
    uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL);
    Input.tty->data = this;
    this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty);

    this->Output.tty = new uv_tty_t;
    uv_tty_init(this->Loop(), this->Output.tty, 1, 0);
    uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL);
    Output.tty->data = this;
    this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty);
  } else {
    usesTty = false;
    this->Input.pipe = new uv_pipe_t;
    uv_pipe_init(this->Loop(), this->Input.pipe, 0);
    uv_pipe_open(this->Input.pipe, 0);
    Input.pipe->data = this;
    this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe);

    this->Output.pipe = new uv_pipe_t;
    uv_pipe_init(this->Loop(), this->Output.pipe, 0);
    uv_pipe_open(this->Output.pipe, 1);
    Output.pipe->data = this;
    this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe);
  }

  SendGreetings();
  uv_read_start(this->ReadStream, on_alloc_buffer, on_read);

  return true;
}

void cmServerStdIoConnection::TearDown()
{
  if (usesTty) {
    uv_close(reinterpret_cast<uv_handle_t*>(this->Input.tty), &on_tty_close);
    uv_close(reinterpret_cast<uv_handle_t*>(this->Output.tty), &on_tty_close);
    this->Input.tty = nullptr;
    this->Output.tty = nullptr;
  } else {
    uv_close(reinterpret_cast<uv_handle_t*>(this->Input.pipe), &on_pipe_close);
    uv_close(reinterpret_cast<uv_handle_t*>(this->Output.pipe),
             &on_pipe_close);
    this->Input.pipe = nullptr;
    this->Input.pipe = nullptr;
  }
  this->ReadStream = nullptr;
  this->WriteStream = nullptr;
}

cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
  : PipeName(name)
{
}

bool cmServerPipeConnection::DoSetup(std::string* errorMessage)
{
  this->ServerPipe = new uv_pipe_t;
  uv_pipe_init(this->Loop(), this->ServerPipe, 0);
  this->ServerPipe->data = this;

  int r;
  if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
    *errorMessage = std::string("Internal Error with ") + this->PipeName +
      ": " + uv_err_name(r);
    return false;
  }
  auto serverStream = reinterpret_cast<uv_stream_t*>(this->ServerPipe);
  if ((r = uv_listen(serverStream, 1, on_new_connection)) != 0) {
    *errorMessage = std::string("Internal Error listening on ") +
      this->PipeName + ": " + uv_err_name(r);
    return false;
  }

  return true;
}

void cmServerPipeConnection::TearDown()
{
  if (this->ClientPipe) {
    uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe), &on_pipe_close);
    this->WriteStream->data = nullptr;
  }
  uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe), &on_pipe_close);

  this->ClientPipe = nullptr;
  this->ServerPipe = nullptr;
  this->WriteStream = nullptr;
  this->ReadStream = nullptr;
}

void cmServerPipeConnection::Connect(uv_stream_t* server)
{
  if (this->ClientPipe) {
    // Accept and close all pipes but the first:
    uv_pipe_t* rejectPipe = new uv_pipe_t;

    uv_pipe_init(this->Loop(), rejectPipe, 0);
    auto rejecter = reinterpret_cast<uv_stream_t*>(rejectPipe);
    uv_accept(server, rejecter);
    uv_close(reinterpret_cast<uv_handle_t*>(rejecter), &on_pipe_close);
    return;
  }

  this->ClientPipe = new uv_pipe_t;
  uv_pipe_init(this->Loop(), this->ClientPipe, 0);
  this->ClientPipe->data = this;
  auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe);
  if (uv_accept(server, client) != 0) {
    uv_close(reinterpret_cast<uv_handle_t*>(client), nullptr);
    return;
  }
  this->ReadStream = client;
  this->WriteStream = client;

  uv_read_start(this->ReadStream, on_alloc_buffer, on_read);

  this->SendGreetings();
}
