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

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

#include <cm/memory>

#include <cm3p/uv.h>

namespace cm {

template <typename T>
struct uv_handle_deleter;

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*() const
{
  return this->loop.get();
}

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

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

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)
{
  this->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.
  */
  this->handle.reset(static_cast<T*>(calloc(1, sizeof(T))),
                     uv_handle_deleter<T>());
  this->handle->data = data;
}

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

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

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

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

template <typename T>
T* uv_handle_ptr_base_<T>::get() const
{
  return this->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>
{
  /***
   * While 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(*this->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)
{
  this->allocate(data);
  return uv_async_init(&loop, this->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)
{
  this->allocate(data);
  return uv_signal_init(&loop, this->handle.get());
}

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

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

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

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

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

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

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

void uv_timer_ptr::stop()
{
  assert(this->handle);
  uv_timer_stop(*this);
}

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

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

int uv_idle_ptr::init(uv_loop_t& loop, void* data)
{
  this->allocate(data);
  return uv_idle_init(&loop, *this);
}

int uv_idle_ptr::start(uv_idle_cb cb)
{
  assert(this->handle);
  return uv_idle_start(*this, cb);
}

void uv_idle_ptr::stop()
{
  assert(this->handle);
  uv_idle_stop(*this);
}

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(idle)

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

namespace {
struct write_req : public uv_write_t
{
  std::weak_ptr<std::function<void(int)>> cb_;
  write_req(std::weak_ptr<std::function<void(int)>> wcb)
    : cb_(std::move(wcb))
  {
  }
};

void write_req_cb(uv_write_t* req, int status)
{
  // Ownership has been transferred from the event loop.
  std::unique_ptr<write_req> self(static_cast<write_req*>(req));

  // Notify the original uv_write caller if it is still interested.
  if (auto cb = self->cb_.lock()) {
    (*cb)(status);
  }
}
}

int uv_write(uv_stream_t* handle, uv_buf_t const bufs[], unsigned int nbufs,
             std::weak_ptr<std::function<void(int)>> cb)
{
  auto req = cm::make_unique<write_req>(std::move(cb));
  int status = uv_write(req.get(), handle, bufs, nbufs, write_req_cb);
  if (status == 0) {
    // Ownership has been transferred to the event loop.
    static_cast<void>(req.release());
  }
  return status;
}
}
