/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <assert.h>
#include <limits.h>

#include "uv.h"
#include "internal.h"
#include "tree.h"
#include "handle-inl.h"


void uv_update_time(uv_loop_t* loop) {
  DWORD ticks = GetTickCount();

  /* The assumption is made that LARGE_INTEGER.QuadPart has the same type */
  /* loop->time, which happens to be. Is there any way to assert this? */
  LARGE_INTEGER* time = (LARGE_INTEGER*) &loop->time;

  /* If the timer has wrapped, add 1 to it's high-order dword. */
  /* uv_poll must make sure that the timer can never overflow more than */
  /* once between two subsequent uv_update_time calls. */
  if (ticks < time->LowPart) {
    time->HighPart += 1;
  }
  time->LowPart = ticks;
}


static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
  if (a->due < b->due)
    return -1;
  if (a->due > b->due)
    return 1;
  /*
   *  compare start_id when both has the same due. start_id is
   *  allocated with loop->timer_counter in uv_timer_start().
   */
  if (a->start_id < b->start_id)
    return -1;
  if (a->start_id > b->start_id)
    return 1;
  return 0;
}


RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare);


int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
  uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER);
  handle->timer_cb = NULL;
  handle->repeat = 0;

  return 0;
}


void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
  if (handle->flags & UV__HANDLE_CLOSING) {
    assert(!(handle->flags & UV_HANDLE_CLOSED));
    uv__handle_close(handle);
  }
}


static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) {
  uint64_t clamped_timeout;

  clamped_timeout = loop_time + timeout;
  if (clamped_timeout < timeout)
    clamped_timeout = (uint64_t) -1;

  return clamped_timeout;
}


int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
    uint64_t repeat) {
  uv_loop_t* loop = handle->loop;
  uv_timer_t* old;

  if (handle->flags & UV_HANDLE_ACTIVE) {
    RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
  }

  handle->timer_cb = timer_cb;
  handle->due = get_clamped_due_time(loop->time, timeout);
  handle->repeat = repeat;
  handle->flags |= UV_HANDLE_ACTIVE;
  uv__handle_start(handle);

  /* start_id is the second index to be compared in uv__timer_cmp() */
  handle->start_id = handle->loop->timer_counter++;

  old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle);
  assert(old == NULL);

  return 0;
}


int uv_timer_stop(uv_timer_t* handle) {
  uv_loop_t* loop = handle->loop;

  if (!(handle->flags & UV_HANDLE_ACTIVE))
    return 0;

  RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);

  handle->flags &= ~UV_HANDLE_ACTIVE;
  uv__handle_stop(handle);

  return 0;
}


int uv_timer_again(uv_timer_t* handle) {
  uv_loop_t* loop = handle->loop;

  /* If timer_cb is NULL that means that the timer was never started. */
  if (!handle->timer_cb) {
    uv__set_sys_error(loop, ERROR_INVALID_DATA);
    return -1;
  }

  if (handle->flags & UV_HANDLE_ACTIVE) {
    RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
    handle->flags &= ~UV_HANDLE_ACTIVE;
    uv__handle_stop(handle);
  }

  if (handle->repeat) {
    handle->due = get_clamped_due_time(loop->time, handle->repeat);

    if (RB_INSERT(uv_timer_tree_s, &loop->timers, handle) != NULL) {
      uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
    }

    handle->flags |= UV_HANDLE_ACTIVE;
    uv__handle_start(handle);
  }

  return 0;
}


void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
  assert(handle->type == UV_TIMER);
  handle->repeat = repeat;
}


uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
  assert(handle->type == UV_TIMER);
  return handle->repeat;
}


DWORD uv_get_poll_timeout(uv_loop_t* loop) {
  uv_timer_t* timer;
  int64_t delta;

  /* Check if there are any running timers */
  timer = RB_MIN(uv_timer_tree_s, &loop->timers);
  if (timer) {
    uv_update_time(loop);

    delta = timer->due - loop->time;
    if (delta >= UINT_MAX >> 1) {
      /* A timeout value of UINT_MAX means infinite, so that's no good. But */
      /* more importantly, there's always the risk that GetTickCount wraps. */
      /* uv_update_time can detect this, but we must make sure that the */
      /* tick counter never overflows twice between two subsequent */
      /* uv_update_time calls. We do this by never sleeping more than half */
      /* the time it takes to wrap  the counter - which is huge overkill, */
      /* but hey, it's not so bad to wake up every 25 days. */
      return UINT_MAX >> 1;
    } else if (delta < 0) {
      /* Negative timeout values are not allowed */
      return 0;
    } else {
      return (DWORD)delta;
    }
  } else {
    /* No timers */
    return INFINITE;
  }
}


void uv_process_timers(uv_loop_t* loop) {
  uv_timer_t* timer;

  /* Call timer callbacks */
  for (timer = RB_MIN(uv_timer_tree_s, &loop->timers);
       timer != NULL && timer->due <= loop->time;
       timer = RB_MIN(uv_timer_tree_s, &loop->timers)) {
    RB_REMOVE(uv_timer_tree_s, &loop->timers, timer);

    if (timer->repeat != 0) {
      /* If it is a repeating timer, reschedule with repeat timeout. */
      timer->due = get_clamped_due_time(timer->due, timer->repeat);
      if (timer->due < loop->time) {
        timer->due = loop->time;
      }
      if (RB_INSERT(uv_timer_tree_s, &loop->timers, timer) != NULL) {
        uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
      }
    } else {
      /* If non-repeating, mark the timer as inactive. */
      timer->flags &= ~UV_HANDLE_ACTIVE;
      uv__handle_stop(timer);
    }

    timer->timer_cb((uv_timer_t*) timer, 0);
  }
}
