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

#include <algorithm>
#include <cassert>
#include <cstring>
#include <stdexcept>
#include <utility>

namespace cmDebugger {

#ifdef _WIN32

DuplexPipe_WIN32::DuplexPipe_WIN32(HANDLE pipe)
  : hPipe(pipe)
{
  readOp.Offset = readOp.OffsetHigh = 0;
  readOp.hEvent = CreateEvent(NULL, true, false, NULL);
  writeOp.Offset = readOp.OffsetHigh = 0;
  writeOp.hEvent = CreateEvent(NULL, true, false, NULL);
}

DuplexPipe_WIN32::~DuplexPipe_WIN32()
{
  close();
}

size_t DuplexPipe_WIN32::read(void* buffer, size_t n)
{
  if (hPipe != INVALID_HANDLE_VALUE) {
    readOp.Offset = readOp.OffsetHigh = 0;
    ResetEvent(readOp.hEvent);
    auto r = ReadFile(hPipe, buffer, n, NULL, &readOp);
    auto err = GetLastError();
    if (r || err == ERROR_IO_PENDING) {
      DWORD nRead = 0;
      if (GetOverlappedResult(hPipe, &readOp, &nRead, true)) {
        return nRead;
      }
    }
  }

  return 0;
}

bool DuplexPipe_WIN32::write(void const* buffer, size_t n)
{
  if (hPipe != INVALID_HANDLE_VALUE) {
    writeOp.Offset = writeOp.OffsetHigh = 0;
    ResetEvent(writeOp.hEvent);
    auto w = WriteFile(hPipe, buffer, n, NULL, &writeOp);
    auto err = GetLastError();
    if (w || err == ERROR_IO_PENDING) {
      DWORD nWrite = 0;
      if (GetOverlappedResult(hPipe, &writeOp, &nWrite, true)) {
        return n == nWrite;
      }
    }
  }

  return false;
}

void DuplexPipe_WIN32::close()
{
  CloseHandle(hPipe);
  hPipe = INVALID_HANDLE_VALUE;
  CloseHandle(readOp.hEvent);
  CloseHandle(writeOp.hEvent);
  readOp.hEvent = writeOp.hEvent = INVALID_HANDLE_VALUE;
}

bool DuplexPipe_WIN32::WaitForConnection()
{
  auto connect = ConnectNamedPipe(hPipe, &readOp);
  auto err = GetLastError();
  if (!connect && err == ERROR_IO_PENDING) {
    DWORD ignored;
    if (GetOverlappedResult(hPipe, &readOp, &ignored, true)) {
      return true;
    }
  }

  return connect || err == ERROR_PIPE_CONNECTED;
}

cmDebuggerPipeConnection_WIN32::cmDebuggerPipeConnection_WIN32(
  std::string name)
  : PipeName(std::move(name))
  , pipes(nullptr)
{
}

cmDebuggerPipeConnection_WIN32::~cmDebuggerPipeConnection_WIN32()
{
  if (isOpen()) {
    pipes = nullptr;
  }
}

bool cmDebuggerPipeConnection_WIN32::StartListening(std::string& errorMessage)
{
  bool result = true;

  auto hPipe = CreateNamedPipeA(
    PipeName.c_str(),
    PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS, 1,
    1024 * 16, 1024 * 16, NMPWAIT_USE_DEFAULT_WAIT, NULL);

  if (hPipe == INVALID_HANDLE_VALUE) {
    auto err = GetLastError();
    errorMessage = GetErrorMessage(err);
    result = false;
  }

  if (result) {
    pipes = std::make_unique<DuplexPipe_WIN32>(hPipe);
  }

  StartedListening.set_value();
  return result;
}

std::string cmDebuggerPipeConnection_WIN32::GetErrorMessage(DWORD errorCode)
{
  LPSTR message = nullptr;
  DWORD size = FormatMessageA(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS,
    nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPSTR)&message, 0, nullptr);
  std::string errorMessage = "Internal Error with " + this->PipeName + ": " +
    std::string(message, size);
  LocalFree(message);
  return errorMessage;
}

std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_WIN32::GetReader()
{
  return std::static_pointer_cast<dap::Reader>(shared_from_this());
}

std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_WIN32::GetWriter()
{
  return std::static_pointer_cast<dap::Writer>(shared_from_this());
}

bool cmDebuggerPipeConnection_WIN32::isOpen()
{
  return pipes != nullptr;
}

void cmDebuggerPipeConnection_WIN32::close()
{
  CloseConnection();
}

void cmDebuggerPipeConnection_WIN32::CloseConnection()
{
  if (isOpen()) {
    pipes->close();
    pipes = nullptr;
  }
}

void cmDebuggerPipeConnection_WIN32::WaitForConnection()
{
  if (!isOpen()) {
    return;
  }

  if (pipes->WaitForConnection()) {
    return;
  }

  CloseConnection();
}

size_t cmDebuggerPipeConnection_WIN32::read(void* buffer, size_t n)
{
  size_t result = 0;
  if (isOpen()) {
    result = pipes->read(buffer, n);
    if (result == 0) {
      CloseConnection();
    }
  }

  return result;
}

bool cmDebuggerPipeConnection_WIN32::write(void const* buffer, size_t n)
{
  bool result = false;
  if (isOpen()) {
    result = pipes->write(buffer, n);
    if (!result) {
      CloseConnection();
    }
  }

  return result;
}

cmDebuggerPipeClient_WIN32::cmDebuggerPipeClient_WIN32(std::string name)
  : PipeName(std::move(name))
{
}

cmDebuggerPipeClient_WIN32::~cmDebuggerPipeClient_WIN32()
{
  close();
}

void cmDebuggerPipeClient_WIN32::WaitForConnection()
{
  if (!isOpen()) {
    auto hPipe = CreateFileA(PipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
                             NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (hPipe == INVALID_HANDLE_VALUE) {
      auto err = GetLastError();
      throw std::runtime_error(std::string("CreateFile failed for pipe ") +
                               GetErrorMessage(err));
    }

    pipes = std::make_unique<DuplexPipe_WIN32>(hPipe);
  }
}

std::string cmDebuggerPipeClient_WIN32::GetErrorMessage(DWORD errorCode)
{
  LPSTR message = nullptr;
  DWORD size = FormatMessageA(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS,
    nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPSTR)&message, 0, nullptr);
  std::string errorMessage =
    this->PipeName + ": " + std::string(message, size);
  LocalFree(message);
  return errorMessage;
}

bool cmDebuggerPipeClient_WIN32::isOpen()
{
  return pipes != nullptr;
}

void cmDebuggerPipeClient_WIN32::close()
{
  if (isOpen()) {
    pipes->close();
    pipes = nullptr;
  }
}

size_t cmDebuggerPipeClient_WIN32::read(void* buffer, size_t n)
{
  size_t result = 0;
  if (isOpen()) {
    result = pipes->read(buffer, n);
    if (result == 0) {
      close();
    }
  }

  return result;
}

bool cmDebuggerPipeClient_WIN32::write(void const* buffer, size_t n)
{
  bool result = false;
  if (isOpen()) {
    result = pipes->write(buffer, n);
    if (!result) {
      close();
    }
  }

  return result;
}

#endif // _WIN32

} // namespace cmDebugger
