/*
 *
 * Copyright 2017 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/iomgr_custom.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/timer_custom.h"

static grpc_custom_timer_vtable* custom_timer_impl;

void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  grpc_core::ExecCtx exec_ctx;
  grpc_timer* timer = t->original;
  GPR_ASSERT(timer->pending);
  timer->pending = 0;
  GRPC_CLOSURE_SCHED(timer->closure, GRPC_ERROR_NONE);
  custom_timer_impl->stop(t);
  gpr_free(t);
}

static void timer_init(grpc_timer* timer, grpc_millis deadline,
                       grpc_closure* closure) {
  uint64_t timeout;
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  grpc_millis now = grpc_core::ExecCtx::Get()->Now();
  if (deadline <= grpc_core::ExecCtx::Get()->Now()) {
    GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_NONE);
    timer->pending = false;
    return;
  } else {
    timeout = deadline - now;
  }
  timer->pending = true;
  timer->closure = closure;
  grpc_custom_timer* timer_wrapper =
      (grpc_custom_timer*)gpr_malloc(sizeof(grpc_custom_timer));
  timer_wrapper->timeout_ms = timeout;
  timer->custom_timer = (void*)timer_wrapper;
  timer_wrapper->original = timer;
  custom_timer_impl->start(timer_wrapper);
}

static void timer_cancel(grpc_timer* timer) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  grpc_custom_timer* tw = (grpc_custom_timer*)timer->custom_timer;
  if (timer->pending) {
    timer->pending = 0;
    GRPC_CLOSURE_SCHED(timer->closure, GRPC_ERROR_CANCELLED);
    custom_timer_impl->stop(tw);
    gpr_free(tw);
  }
}

static grpc_timer_check_result timer_check(grpc_millis* next) {
  return GRPC_TIMERS_NOT_CHECKED;
}

static void timer_list_init() {}
static void timer_list_shutdown() {}

static void timer_consume_kick(void) {}

static grpc_timer_vtable custom_timer_vtable = {
    timer_init,      timer_cancel,        timer_check,
    timer_list_init, timer_list_shutdown, timer_consume_kick};

void grpc_custom_timer_init(grpc_custom_timer_vtable* impl) {
  custom_timer_impl = impl;
  grpc_set_timer_impl(&custom_timer_vtable);
}
