#include "uvsignal.h"
#include "uveventloop.h"

namespace myapp::async {

namespace {

std::unique_ptr<uv_signal> create_signal(uvw::Loop& loop)
{
    return std::make_unique<uv_signal>(
        loop.resource<uvw::SignalHandle>());
}

template<class Func>
void register_callback(std::shared_ptr<uvw::SignalHandle> signal, Func&& f)
{
    signal->on<uvw::SignalEvent>([callback = std::forward<Func>(f)](uvw::SignalEvent const& e, uvw::SignalHandle&)
    {
        callback(e.signum);
    });
}

} /* namespace myapp::async::{anonymous} */

std::unique_ptr<signal> signal::create(std::shared_ptr<event_loop> loop)
{
    return create_signal(std::static_pointer_cast<uv_event_loop>(loop)->handle());
}

uv_signal::uv_signal(std::shared_ptr<uvw::SignalHandle> handle)
  : signal_(std::move(handle))
{
}

uv_signal::~uv_signal()
{
    signal_->close();
}

void uv_signal::on(int signum, std::function<void(int signum)> callback)
{
    register_callback(signal_, std::move(callback));
    signal_->start(signum);
}

void uv_signal::once(int signum, std::function<void(int signum)> callback)
{
    register_callback(signal_, std::move(callback));
    signal_->oneShot(signum);
}

void uv_signal::stop()
{
    signal_->stop();
}

uvw::SignalHandle& uv_signal::handle() noexcept
{
    return *signal_;
}

uvw::SignalHandle const& uv_signal::handle() const noexcept
{
    return *signal_;
}

} /* namespace myapp::async */
