/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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.
 */

/**
 * @file AsyncTimer.cc
 */
#include "tscpp/api/AsyncTimer.h"
#include "ts/ts.h"
#include "logging_internal.h"

using namespace atscppapi;

struct atscppapi::AsyncTimerState {
  TSCont                                       cont_ = nullptr;
  AsyncTimer::Type                             type_;
  int                                          period_in_ms_;
  int                                          initial_period_in_ms_;
  TSThreadPool                                 thread_pool_;
  TSAction                                     initial_timer_action_  = nullptr;
  TSAction                                     periodic_timer_action_ = nullptr;
  AsyncTimer                                  *timer_                 = nullptr;
  std::shared_ptr<AsyncDispatchControllerBase> dispatch_controller_{};
  AsyncTimerState(AsyncTimer::Type type, int period_in_ms, int initial_period_in_ms, TSThreadPool thread_pool, AsyncTimer *timer)
    : type_(type),
      period_in_ms_(period_in_ms),
      initial_period_in_ms_(initial_period_in_ms),
      thread_pool_(thread_pool),
      timer_(timer)
  {
  }
};

namespace
{
int
handleTimerEvent(TSCont cont, TSEvent /* event ATS_UNUSED */, void * /* edata ATS_UNUSED */)
{
  AsyncTimerState *state = static_cast<AsyncTimerState *>(TSContDataGet(cont));
  if (state->initial_timer_action_) {
    LOG_DEBUG("Received initial timer event.");
    state->initial_timer_action_ = nullptr; // mark it so that it won't be canceled later on
    if (state->type_ == AsyncTimer::TYPE_PERIODIC) {
      LOG_DEBUG("Scheduling periodic event now");
      state->periodic_timer_action_ = TSContScheduleEveryOnPool(state->cont_, state->period_in_ms_, state->thread_pool_);
    }
  }
  if (!state->dispatch_controller_->dispatch()) {
    LOG_DEBUG("Receiver has died. Destroying timer");
    delete state->timer_; // auto-destruct only in this case
  }
  return 0;
}
} // namespace

AsyncTimer::AsyncTimer(Type type, int period_in_ms, int initial_period_in_ms, TSThreadPool thread_pool)
{
  state_        = new AsyncTimerState(type, period_in_ms, initial_period_in_ms, thread_pool, this);
  state_->cont_ = TSContCreate(handleTimerEvent, TSMutexCreate());
  TSContDataSet(state_->cont_, static_cast<void *>(state_));
}

void
AsyncTimer::run()
{
  state_->dispatch_controller_ = getDispatchController(); // keep a copy in state so that cont handler can use it
  int one_off_timeout_in_ms    = 0;
  int regular_timeout_in_ms    = 0;
  if (state_->type_ == AsyncTimer::TYPE_ONE_OFF) {
    one_off_timeout_in_ms = state_->period_in_ms_;
  } else {
    one_off_timeout_in_ms = state_->initial_period_in_ms_;
    regular_timeout_in_ms = state_->period_in_ms_;
  }
  if (one_off_timeout_in_ms) {
    LOG_DEBUG("Scheduling initial/one-off event");
    state_->initial_timer_action_ = TSContScheduleOnPool(state_->cont_, one_off_timeout_in_ms, state_->thread_pool_);
  } else if (regular_timeout_in_ms) {
    LOG_DEBUG("Scheduling regular timer events");
    state_->periodic_timer_action_ = TSContScheduleEveryOnPool(state_->cont_, regular_timeout_in_ms, state_->thread_pool_);
  }
}

void
AsyncTimer::cancel()
{
  // Assume this object is locked and the state isn't being updated elsewhere.
  // Note that is not the same as the contained continuation being locked.
  TSCont contp{state_->cont_}; // save this
  if (!contp) {
    LOG_DEBUG("Already canceled");
    return;
  }

  auto mutex{TSContMutexGet(contp)};
  TSMutexLock(mutex); // prevent event dispatch for the continuation during this cancel.

  if (state_->initial_timer_action_) {
    LOG_DEBUG("Canceling initial timer action");
    TSActionCancel(state_->initial_timer_action_);
  }
  if (state_->periodic_timer_action_) {
    LOG_DEBUG("Canceling periodic timer action");
    TSActionCancel(state_->periodic_timer_action_);
  }
  state_->cont_ = nullptr;

  TSMutexUnlock(mutex);

  LOG_DEBUG("Destroying cont");
  TSContDestroy(contp);
}

AsyncTimer::~AsyncTimer()
{
  cancel();
  delete state_;
}
