/**
  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 TransactionPlugin.cc
 */

#include <memory>
#include <cstddef>
#include <cassert>
#include "ts/ts.h"
#include "tscpp/api/TransactionPlugin.h"
#include "utils_internal.h"
#include "tscpp/api/noncopyable.h"
#include "logging_internal.h"

using namespace atscppapi;
using atscppapi::TransactionPlugin;

/**
 * @private
 */
struct atscppapi::TransactionPluginState : noncopyable {
  TSCont                 cont_ = nullptr;
  TSHttpTxn              ats_txn_handle_;
  std::shared_ptr<Mutex> mutex_;
  TransactionPluginState(TSHttpTxn ats_txn_handle) : ats_txn_handle_(ats_txn_handle), mutex_(new Mutex) {}
};

namespace
{
static int
handleTransactionPluginEvents(TSCont cont, TSEvent event, void *edata)
{
  TSHttpTxn          txn    = static_cast<TSHttpTxn>(edata);
  TransactionPlugin *plugin = static_cast<TransactionPlugin *>(TSContDataGet(cont));
  LOG_DEBUG("cont=%p, event=%d, tshttptxn=%p, plugin=%p", cont, event, edata, plugin);
  atscppapi::utils::internal::invokePluginForEvent(plugin, txn, event);
  return 0;
}

} /* anonymous namespace */

TransactionPlugin::TransactionPlugin(Transaction &transaction)
{
  state_        = std::make_unique<TransactionPluginState>(static_cast<TSHttpTxn>(transaction.getAtsHandle()));
  TSMutex mutex = nullptr;
  state_->cont_ = TSContCreate(handleTransactionPluginEvents, mutex);
  TSContDataSet(state_->cont_, static_cast<void *>(this));
  LOG_DEBUG("Creating new TransactionPlugin=%p tshttptxn=%p, cont=%p", this, state_->ats_txn_handle_, state_->cont_);
}

std::shared_ptr<Mutex>
TransactionPlugin::getMutex()
{
  return state_->mutex_;
}

std::shared_ptr<Mutex>
TransactionPlugin::getMutex(TSHttpTxn txnp)
{
  return state_->ats_txn_handle_ == txnp ? state_->mutex_ : nullptr;
}

bool
TransactionPlugin::isWebsocket() const
{
  return TSHttpTxnIsWebsocket(state_->ats_txn_handle_);
}

TransactionPlugin::~TransactionPlugin()
{
  LOG_DEBUG("Destroying TransactionPlugin=%p", this);
  TSContDestroy(state_->cont_);
}

void
TransactionPlugin::registerHook(Plugin::HookType hook_type)
{
  LOG_DEBUG("TransactionPlugin=%p tshttptxn=%p registering hook_type=%d [%s]", this, state_->ats_txn_handle_, hook_type,
            HOOK_TYPE_STRINGS[hook_type].c_str());
  TSHttpHookID hook_id = atscppapi::utils::internal::convertInternalHookToTsHook(hook_type);
  TSHttpTxnHookAdd(state_->ats_txn_handle_, hook_id, state_->cont_);
}
