/*
 *
 * Copyright 2018 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 <stddef.h>
#include <string.h>

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

#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/iomgr_custom.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/pollset_custom.h"
#include "src/core/lib/iomgr/timer.h"

#include "src/core/lib/debug/trace.h"

static grpc_custom_poller_vtable* poller_vtable;

struct grpc_pollset {
  gpr_mu mu;
};

static size_t pollset_size() { return sizeof(grpc_pollset); }

static void pollset_global_init() { poller_vtable->init(); }

static void pollset_global_shutdown() { poller_vtable->shutdown(); }

static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  gpr_mu_init(&pollset->mu);
  *mu = &pollset->mu;
}

static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_NONE);
}

static void pollset_destroy(grpc_pollset* pollset) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  gpr_mu_destroy(&pollset->mu);
}

static grpc_error* pollset_work(grpc_pollset* pollset,
                                grpc_pollset_worker** worker_hdl,
                                grpc_millis deadline) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  gpr_mu_unlock(&pollset->mu);
  grpc_millis now = grpc_core::ExecCtx::Get()->Now();
  grpc_millis timeout = 0;
  if (deadline > now) {
    timeout = deadline - now;
  }
  // We yield here because the poll() call might yield
  // control back to the application
  grpc_core::ExecCtx* curr = grpc_core::ExecCtx::Get();
  grpc_core::ExecCtx::Set(nullptr);
  poller_vtable->poll(static_cast<size_t>(timeout));
  grpc_core::ExecCtx::Set(curr);
  grpc_core::ExecCtx::Get()->InvalidateNow();
  if (grpc_core::ExecCtx::Get()->HasWork()) {
    grpc_core::ExecCtx::Get()->Flush();
  }
  gpr_mu_lock(&pollset->mu);
  return GRPC_ERROR_NONE;
}

static grpc_error* pollset_kick(grpc_pollset* pollset,
                                grpc_pollset_worker* specific_worker) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  poller_vtable->kick();
  return GRPC_ERROR_NONE;
}

grpc_pollset_vtable custom_pollset_vtable = {
    pollset_global_init, pollset_global_shutdown,
    pollset_init,        pollset_shutdown,
    pollset_destroy,     pollset_work,
    pollset_kick,        pollset_size};

void grpc_custom_pollset_init(grpc_custom_poller_vtable* vtable) {
  poller_vtable = vtable;
  grpc_set_pollset_vtable(&custom_pollset_vtable);
}
