#include <chrono>
#include <iostream>
#include <thread>
#include <utility>

#include <cm3p/uv.h>

#include "cmUVHandlePtr.h"

static void signal_reset_fn(uv_async_t* handle)
{
  auto ptr = static_cast<cm::uv_async_ptr*>(handle->data);
  ptr->reset();
}

// A common pattern is to use an async signal to shutdown the server.
static bool testAsyncShutdown()
{
  uv_loop_t Loop;
  auto err = uv_loop_init(&Loop);
  if (err != 0) {
    std::cerr << "Could not init loop" << std::endl;
    return false;
  }

  {
    cm::uv_async_ptr signal;
    signal.init(Loop, &signal_reset_fn, &signal);

    std::thread([&] {
      std::this_thread::sleep_for(std::chrono::seconds(2));
      signal.send();
    })
      .detach();

    if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
      std::cerr << "Unclean exit state in testAsyncDtor" << std::endl;
      return false;
    }

    if (signal.get()) {
      std::cerr << "Loop exited with signal not being cleaned up" << std::endl;
      return false;
    }
  }

  uv_loop_close(&Loop);

  return true;
}

static void signal_fn(uv_async_t*)
{
}

// Async dtor is sort of a pain; since it locks a mutex we must be sure its
// dtor always calls reset otherwise the mutex is deleted then locked.
static bool testAsyncDtor()
{
  uv_loop_t Loop;
  auto err = uv_loop_init(&Loop);
  if (err != 0) {
    std::cerr << "Could not init loop" << std::endl;
    return false;
  }

  {
    cm::uv_async_ptr signal;
    signal.init(Loop, signal_fn);
  }

  if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
    std::cerr << "Unclean exit state in testAsyncDtor" << std::endl;
    return false;
  }

  uv_loop_close(&Loop);

  return true;
}

// Async needs a relatively stateful deleter; make sure that is properly
// accounted for and doesn't try to hold on to invalid state when it is
// moved
static bool testAsyncMove()
{
  uv_loop_t Loop;
  auto err = uv_loop_init(&Loop);
  if (err != 0) {
    std::cerr << "Could not init loop" << std::endl;
    return false;
  }

  {
    cm::uv_async_ptr signal;
    {
      cm::uv_async_ptr signalTmp;
      signalTmp.init(Loop, signal_fn);
      signal = std::move(signalTmp);
    }
  }

  if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
    std::cerr << "Unclean exit state in testAsyncDtor" << std::endl;
    return false;
  }

  uv_loop_close(&Loop);
  return true;
}

// When a type is castable to another uv type (pipe -> stream) here,
// and the deleter is convertible as well, we should allow moves from
// one type to the other.
static bool testCrossAssignment()
{
  uv_loop_t Loop;
  auto err = uv_loop_init(&Loop);
  if (err != 0) {
    std::cerr << "Could not init loop" << std::endl;
    return false;
  }

  {
    cm::uv_pipe_ptr pipe;
    pipe.init(Loop, 0);

    cm::uv_stream_ptr stream = std::move(pipe);
    if (pipe.get()) {
      std::cerr << "Move should be sure to invalidate the previous ptr"
                << std::endl;
      return false;
    }
    cm::uv_handle_ptr handle = std::move(stream);
    if (stream.get()) {
      std::cerr << "Move should be sure to invalidate the previous ptr"
                << std::endl;
      return false;
    }
  }

  if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
    std::cerr << "Unclean exit state in testCrossAssignment" << std::endl;
    return false;
  }

  uv_loop_close(&Loop);
  return true;
}

// This test can't fail at run time; but this makes sure we have all our move
// ctors created correctly.
static bool testAllMoves()
{
  using namespace cm;
  struct allTypes
  {
    uv_stream_ptr _7;
    uv_timer_ptr _8;
    uv_tty_ptr _9;
    uv_process_ptr _11;
    uv_pipe_ptr _12;
    uv_async_ptr _13;
    uv_signal_ptr _14;
    uv_handle_ptr _15;
  };

  allTypes a;
  allTypes b(std::move(a));
  allTypes c = std::move(b);
  return true;
};

static bool testLoopReset()
{
  bool closed = false;
  cm::uv_loop_ptr loop;
  loop.init();

  uv_timer_t timer;
  uv_timer_init(loop, &timer);
  timer.data = &closed;
  uv_close(reinterpret_cast<uv_handle_t*>(&timer), [](uv_handle_t* handle) {
    auto closedPtr = static_cast<bool*>(handle->data);
    *closedPtr = true;
  });

  loop.reset();
  if (!closed) {
    std::cerr << "uv_loop_ptr did not finish" << std::endl;
    return false;
  }

  return true;
};

static bool testLoopDestructor()
{
  bool closed = false;

  uv_timer_t timer;
  {
    cm::uv_loop_ptr loop;
    loop.init();

    uv_timer_init(loop, &timer);
    timer.data = &closed;
    uv_close(reinterpret_cast<uv_handle_t*>(&timer), [](uv_handle_t* handle) {
      auto closedPtr = static_cast<bool*>(handle->data);
      *closedPtr = true;
    });
  }

  if (!closed) {
    std::cerr << "uv_loop_ptr did not finish" << std::endl;
    return false;
  }

  return true;
};

int testUVRAII(int, char** const)
{
  if ((testAsyncShutdown() &&
       testAsyncDtor() & testAsyncMove() & testCrossAssignment() &
         testAllMoves() & testLoopReset() & testLoopDestructor()) == 0) {
    return -1;
  }
  return 0;
}
