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

#include <cassert>
#include <cstdlib>
#include <mutex>

#include "cm_uv.h"

namespace cm {

struct uv_loop_deleter
{
  void operator()(uv_loop_t* loop) const;
};

void uv_loop_deleter::operator()(uv_loop_t* loop) const
{
  uv_run(loop, UV_RUN_DEFAULT);
  int result = uv_loop_close(loop);
  (void)result;
  assert(result >= 0);
  free(loop);
}

int uv_loop_ptr::init(void* data)
{
  this->reset();

  this->loop.reset(static_cast<uv_loop_t*>(calloc(1, sizeof(uv_loop_t))),
                   uv_loop_deleter());
  this->loop->data = data;

  return uv_loop_init(this->loop.get());
}

void uv_loop_ptr::reset()
{
  this->loop.reset();
}

uv_loop_ptr::operator uv_loop_t*()
{
  return this->loop.get();
}

uv_loop_t* uv_loop_ptr::operator->() const noexcept
{
  return this->loop.get();
}

uv_loop_t* uv_loop_ptr::get() const
{
  return this->loop.get();
}

template <typename T>
static void handle_default_delete(T* type_handle)
{
  auto handle = reinterpret_cast<uv_handle_t*>(type_handle);
  if (handle) {
    assert(!uv_is_closing(handle));
    if (!uv_is_closing(handle)) {
      uv_close(handle, [](uv_handle_t* h) { free(h); });
    }
  }
}

/**
 * Encapsulates delete logic for a given handle type T
 */
template <typename T>
struct uv_handle_deleter
{
  void operator()(T* type_handle) const { handle_default_delete(type_handle); }
};

template <typename T>
void uv_handle_ptr_base_<T>::allocate(void* data)
{
  reset();

  /*
    We use calloc since we know all these types are c structs
    and we just want to 0 init them. New would do the same thing;
    but casting from uv_handle_t to certain other types -- namely
    uv_timer_t -- triggers a cast_align warning on certain systems.
  */
  handle.reset(static_cast<T*>(calloc(1, sizeof(T))), uv_handle_deleter<T>());
  handle->data = data;
}

template <typename T>
void uv_handle_ptr_base_<T>::reset()
{
  handle.reset();
}

template <typename T>
uv_handle_ptr_base_<T>::operator uv_handle_t*()
{
  return reinterpret_cast<uv_handle_t*>(handle.get());
}

template <typename T>
T* uv_handle_ptr_base_<T>::operator->() const noexcept
{
  return handle.get();
}

template <typename T>
T* uv_handle_ptr_base_<T>::get() const
{
  return handle.get();
}

template <typename T>
uv_handle_ptr_<T>::operator T*() const
{
  return this->handle.get();
}

#ifndef CMAKE_BOOTSTRAP
template <>
struct uv_handle_deleter<uv_async_t>
{
  /***
   * Wile uv_async_send is itself thread-safe, there are
   * no strong guarantees that close hasn't already been
   * called on the handle; and that it might be deleted
   * as the send call goes through. This mutex guards
   * against that.
   *
   * The shared_ptr here is to allow for copy construction
   * which is mandated by the standard for Deleter on
   * shared_ptrs.
   */
  std::shared_ptr<std::mutex> handleMutex;

  uv_handle_deleter()
    : handleMutex(std::make_shared<std::mutex>())
  {
  }

  void operator()(uv_async_t* handle)
  {
    std::lock_guard<std::mutex> lock(*handleMutex);
    handle_default_delete(handle);
  }
};

void uv_async_ptr::send()
{
  auto deleter = std::get_deleter<uv_handle_deleter<uv_async_t>>(this->handle);
  assert(deleter);

  std::lock_guard<std::mutex> lock(*deleter->handleMutex);
  if (this->handle) {
    uv_async_send(*this);
  }
}

int uv_async_ptr::init(uv_loop_t& loop, uv_async_cb async_cb, void* data)
{
  allocate(data);
  return uv_async_init(&loop, handle.get(), async_cb);
}
#endif

template <>
struct uv_handle_deleter<uv_signal_t>
{
  void operator()(uv_signal_t* handle) const
  {
    if (handle) {
      uv_signal_stop(handle);
      handle_default_delete(handle);
    }
  }
};

int uv_signal_ptr::init(uv_loop_t& loop, void* data)
{
  allocate(data);
  return uv_signal_init(&loop, handle.get());
}

int uv_signal_ptr::start(uv_signal_cb cb, int signum)
{
  assert(handle);
  return uv_signal_start(*this, cb, signum);
}

void uv_signal_ptr::stop()
{
  if (handle) {
    uv_signal_stop(*this);
  }
}

int uv_pipe_ptr::init(uv_loop_t& loop, int ipc, void* data)
{
  allocate(data);
  return uv_pipe_init(&loop, *this, ipc);
}

uv_pipe_ptr::operator uv_stream_t*() const
{
  return reinterpret_cast<uv_stream_t*>(handle.get());
}

int uv_process_ptr::spawn(uv_loop_t& loop, uv_process_options_t const& options,
                          void* data)
{
  allocate(data);
  return uv_spawn(&loop, *this, &options);
}

int uv_timer_ptr::init(uv_loop_t& loop, void* data)
{
  allocate(data);
  return uv_timer_init(&loop, *this);
}

int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
{
  assert(handle);
  return uv_timer_start(*this, cb, timeout, repeat);
}

#ifndef CMAKE_BOOTSTRAP
uv_tty_ptr::operator uv_stream_t*() const
{
  return reinterpret_cast<uv_stream_t*>(handle.get());
}

int uv_tty_ptr::init(uv_loop_t& loop, int fd, int readable, void* data)
{
  allocate(data);
  return uv_tty_init(&loop, *this, fd, readable);
}
#endif

template class uv_handle_ptr_base_<uv_handle_t>;

#define UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(NAME)                              \
  template class uv_handle_ptr_base_<uv_##NAME##_t>;                          \
  template class uv_handle_ptr_<uv_##NAME##_t>;

UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(signal)

UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(pipe)

UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream)

UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process)

UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer)

#ifndef CMAKE_BOOTSTRAP
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async)

UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty)
#endif
}
