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

#include <cassert>
#include <cstring>

#include <cm3p/uv.h>

#include "cmServer.h"

struct write_req_t
{
  uv_write_t req;
  uv_buf_t buf;
};

void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle,
                                             size_t suggested_size,
                                             uv_buf_t* buf)
{
  (void)(handle);
#ifndef __clang_analyzer__
  char* rawBuffer = new char[suggested_size];
  *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
#else
  (void)(suggested_size);
  (void)(buf);
#endif /* __clang_analyzer__ */
}

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

  delete[](buf->base);
}

void cmEventBasedConnection::on_close(uv_handle_t* /*handle*/)
{
}

void cmEventBasedConnection::on_write(uv_write_t* req, int status)
{
  (void)(status);

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

void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status)
{
  (void)(status);
  auto conn = static_cast<cmEventBasedConnection*>(stream->data);

  if (conn) {
    conn->Connect(stream);
  }
}

bool cmEventBasedConnection::IsOpen() const
{
  return this->WriteStream != nullptr;
}

void cmEventBasedConnection::WriteData(const std::string& _data)
{
#ifndef NDEBUG
  auto curr_thread_id = uv_thread_self();
  assert(this->Server);
  assert(uv_thread_equal(&curr_thread_id, &this->Server->ServeThreadId));
#endif

#ifndef __clang_analyzer__
  auto data = _data;
  assert(this->WriteStream.get());
  if (BufferStrategy) {
    data = BufferStrategy->BufferOutMessage(data);
  }

  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), this->WriteStream, &req->buf, 1,
           on_write);
#else
  (void)(_data);
#endif /* __clang_analyzer__ */
}

void cmEventBasedConnection::ReadData(const std::string& data)
{
  this->RawReadBuffer += data;
  if (BufferStrategy) {
    std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
    while (!packet.empty()) {
      ProcessRequest(packet);
      packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
    }
  } else {
    ProcessRequest(this->RawReadBuffer);
    this->RawReadBuffer.clear();
  }
}

cmEventBasedConnection::cmEventBasedConnection(
  cmConnectionBufferStrategy* bufferStrategy)
  : BufferStrategy(bufferStrategy)
{
}

void cmEventBasedConnection::Connect(uv_stream_t* server)
{
  (void)server;
  Server->OnConnected(nullptr);
}

void cmEventBasedConnection::OnDisconnect(int onerror)
{
  (void)onerror;
  this->OnConnectionShuttingDown();
  if (this->Server) {
    this->Server->OnDisconnect(this);
  }
}

cmConnection::~cmConnection() = default;

bool cmConnection::OnConnectionShuttingDown()
{
  this->Server = nullptr;
  return true;
}

void cmConnection::SetServer(cmServerBase* s)
{
  Server = s;
}

void cmConnection::ProcessRequest(const std::string& request)
{
  Server->ProcessRequest(this, request);
}

bool cmConnection::OnServeStart(std::string* errString)
{
  (void)errString;
  return true;
}

bool cmEventBasedConnection::OnConnectionShuttingDown()
{
  if (this->WriteStream.get()) {
    this->WriteStream->data = nullptr;
  }

  WriteStream.reset();

  return true;
}
