/**
  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 utils_internal.cc
 */
#include "utils_internal.h"
#include <cassert>
#include "ts/ts.h"
#include <pthread.h>
#include <cstdlib>
#include <cassert>
#include <cstddef>
#include <mutex>
#include "tscpp/api/Plugin.h"
#include "tscpp/api/GlobalPlugin.h"
#include "tscpp/api/Transaction.h"
#include "tscpp/api/TransactionPlugin.h"
#include "tscpp/api/TransformationPlugin.h"
#include "tscpp/api/utils.h"
#include "logging_internal.h"

using namespace atscppapi;

namespace
{
/// The index used to store required transaction based data.
int TRANSACTION_STORAGE_INDEX = -1;

void
resetTransactionHandles(Transaction &transaction, TSEvent /* event ATS_UNUSED */)
{
  utils::internal::resetTransactionHandles(transaction);
  return;
}

void
cleanupTransaction(Transaction &transaction, TSHttpTxn ats_txn_handle)
{
  delete &transaction;
  // reset the txn arg to prevent use-after-free
  TSUserArgSet(ats_txn_handle, TRANSACTION_STORAGE_INDEX, nullptr);
}

void
cleanupTransactionPlugin(Plugin *plugin, TSHttpTxn ats_txn_handle)
{
  TransactionPlugin     *transaction_plugin = static_cast<TransactionPlugin *>(plugin);
  std::shared_ptr<Mutex> trans_mutex        = utils::internal::getTransactionPluginMutex(*transaction_plugin, ats_txn_handle);
  if (trans_mutex == nullptr) {
    LOG_ERROR("TransactionPlugin use-after-free! plugin %p, txn %p", plugin, ats_txn_handle);
    return;
  }
  LOG_DEBUG("Locking TransactionPlugin mutex to delete transaction plugin at %p", transaction_plugin);
  trans_mutex->lock();
  delete transaction_plugin;
  trans_mutex->unlock();
}

int
handleTransactionEvents(TSCont cont, TSEvent event, void *edata)
{
  // This function is only here to clean up Transaction objects
  TSHttpTxn    ats_txn_handle = static_cast<TSHttpTxn>(edata);
  Transaction &transaction    = utils::internal::getTransaction(ats_txn_handle);
  LOG_DEBUG("Got event %d on continuation %p for transaction (ats pointer %p, object %p)", event, cont, ats_txn_handle,
            &transaction);

  utils::internal::setTransactionEvent(transaction, event);
  switch (event) {
  case TS_EVENT_HTTP_POST_REMAP:
    // This is here to force a refresh of the cached client request url
    TSMBuffer hdr_buf;
    TSMLoc    hdr_loc;
    (void)TSHttpTxnClientReqGet(static_cast<TSHttpTxn>(transaction.getAtsHandle()), &hdr_buf, &hdr_loc);
    break;
  case TS_EVENT_HTTP_SEND_REQUEST_HDR:
  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
  case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
  case TS_EVENT_HTTP_READ_CACHE_HDR:
    // the buffer handles may be destroyed in the core during redirect follow
    resetTransactionHandles(transaction, event);
    break;
  case TS_EVENT_HTTP_TXN_CLOSE: { // opening scope to declare plugins variable below
    resetTransactionHandles(transaction, event);
    const std::list<TransactionPlugin *> &plugins = utils::internal::getTransactionPlugins(transaction);
    for (auto plugin : plugins) {
      cleanupTransactionPlugin(plugin, ats_txn_handle);
    }
    cleanupTransaction(transaction, ats_txn_handle);
  } break;
  default:
    assert(false); /* we should never get here */
    break;
  }
  TSHttpTxnReenable(ats_txn_handle, TS_EVENT_HTTP_CONTINUE);
  return 0;
}

void
setupTransactionManagement()
{
  // Reserve a transaction slot
  TSAssert(TS_SUCCESS == TSUserArgIndexReserve(TS_USER_ARGS_TXN, "atscppapi", "ATS CPP API", &TRANSACTION_STORAGE_INDEX));
  // We must always have a cleanup handler available
  TSMutex mutex = nullptr;
  TSCont  cont  = TSContCreate(handleTransactionEvents, mutex);
  TSHttpHookAdd(TS_HTTP_POST_REMAP_HOOK, cont);
  TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, cont);
  TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, cont);
  TSHttpHookAdd(TS_HTTP_SEND_RESPONSE_HDR_HOOK, cont);
  TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, cont);
  TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, cont);
}

void inline invokePluginForEvent(Plugin *plugin, TSHttpTxn ats_txn_handle, TSEvent event)
{
  Transaction &transaction = utils::internal::getTransaction(ats_txn_handle);
  switch (event) {
  case TS_EVENT_HTTP_PRE_REMAP:
    plugin->handleReadRequestHeadersPreRemap(transaction);
    break;
  case TS_EVENT_HTTP_POST_REMAP:
    plugin->handleReadRequestHeadersPostRemap(transaction);
    break;
  case TS_EVENT_HTTP_SEND_REQUEST_HDR:
    plugin->handleSendRequestHeaders(transaction);
    break;
  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
    plugin->handleReadResponseHeaders(transaction);
    break;
  case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
    plugin->handleSendResponseHeaders(transaction);
    break;
  case TS_EVENT_HTTP_OS_DNS:
    plugin->handleOsDns(transaction);
    break;
  case TS_EVENT_HTTP_READ_REQUEST_HDR:
    plugin->handleReadRequestHeaders(transaction);
    break;
  case TS_EVENT_HTTP_READ_CACHE_HDR:
    plugin->handleReadCacheHeaders(transaction);
    break;
  case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
    plugin->handleReadCacheLookupComplete(transaction);
    break;
  case TS_EVENT_HTTP_TXN_CLOSE:
    if (plugin) {
      plugin->handleTxnClose(transaction);
      cleanupTransactionPlugin(plugin, ats_txn_handle);
    } else {
      LOG_ERROR("stray event TS_EVENT_HTTP_TXN_CLOSE, no transaction plugin to handle it!");
    }
    cleanupTransaction(transaction, ats_txn_handle);
    break;
  default:
    assert(false); /* we should never get here */
    break;
  }
}

} /* anonymous namespace */

Transaction &
utils::internal::getTransaction(TSHttpTxn ats_txn_handle)
{
  Transaction *transaction = static_cast<Transaction *>(TSUserArgGet(ats_txn_handle, TRANSACTION_STORAGE_INDEX));
  if (!transaction) {
    transaction = new Transaction(static_cast<void *>(ats_txn_handle));
    LOG_DEBUG("Created new transaction object at %p for ats pointer %p", transaction, ats_txn_handle);
    TSUserArgSet(ats_txn_handle, TRANSACTION_STORAGE_INDEX, transaction);
  }
  return *transaction;
}

std::shared_ptr<Mutex>
utils::internal::getTransactionPluginMutex(TransactionPlugin &transaction_plugin, TSHttpTxn txnp)
{
  return transaction_plugin.getMutex(txnp);
}

TSHttpHookID
utils::internal::convertInternalHookToTsHook(Plugin::HookType hooktype)
{
  switch (hooktype) {
  case Plugin::HOOK_READ_REQUEST_HEADERS_POST_REMAP:
    return TS_HTTP_POST_REMAP_HOOK;
  case Plugin::HOOK_READ_REQUEST_HEADERS_PRE_REMAP:
    return TS_HTTP_PRE_REMAP_HOOK;
  case Plugin::HOOK_READ_RESPONSE_HEADERS:
    return TS_HTTP_READ_RESPONSE_HDR_HOOK;
  case Plugin::HOOK_SEND_REQUEST_HEADERS:
    return TS_HTTP_SEND_REQUEST_HDR_HOOK;
  case Plugin::HOOK_SEND_RESPONSE_HEADERS:
    return TS_HTTP_SEND_RESPONSE_HDR_HOOK;
  case Plugin::HOOK_OS_DNS:
    return TS_HTTP_OS_DNS_HOOK;
  case Plugin::HOOK_READ_REQUEST_HEADERS:
    return TS_HTTP_READ_REQUEST_HDR_HOOK;
  case Plugin::HOOK_READ_CACHE_HEADERS:
    return TS_HTTP_READ_CACHE_HDR_HOOK;
  case Plugin::HOOK_CACHE_LOOKUP_COMPLETE:
    return TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK;
  case Plugin::HOOK_SELECT_ALT:
    return TS_HTTP_SELECT_ALT_HOOK;
  case Plugin::HOOK_TXN_CLOSE:
    return TS_HTTP_TXN_CLOSE_HOOK;
  default:
    assert(false); // shouldn't happen, let's catch it early
    break;
  }
  return static_cast<TSHttpHookID>(-1);
}

TSHttpHookID
utils::internal::convertInternalTransformationTypeToTsHook(TransformationPlugin::Type type)
{
  switch (type) {
  case TransformationPlugin::RESPONSE_TRANSFORMATION:
    return TS_HTTP_RESPONSE_TRANSFORM_HOOK;
  case TransformationPlugin::REQUEST_TRANSFORMATION:
    return TS_HTTP_REQUEST_TRANSFORM_HOOK;
  case TransformationPlugin::CLIENT_RESPONSE_SINK_TRANSFORMATION:
    return TS_HTTP_RESPONSE_CLIENT_HOOK;
  case TransformationPlugin::CLIENT_REQUEST_SINK_TRANSFORMATION:
    return TS_HTTP_REQUEST_CLIENT_HOOK;
  default:
    assert(false); // shouldn't happen, let's catch it early
    break;
  }
  return static_cast<TSHttpHookID>(-1);
}

void
utils::internal::invokePluginForEvent(TransactionPlugin *plugin, TSHttpTxn ats_txn_handle, TSEvent event)
{
  std::lock_guard<Mutex> scopedLock(*(plugin->getMutex()));
  ::invokePluginForEvent(static_cast<Plugin *>(plugin), ats_txn_handle, event);
}

void
utils::internal::invokePluginForEvent(GlobalPlugin *plugin, TSHttpTxn ats_txn_handle, TSEvent event)
{
  ::invokePluginForEvent(static_cast<Plugin *>(plugin), ats_txn_handle, event);
}

void
utils::internal::invokePluginForEvent(GlobalPlugin *plugin, TSHttpAltInfo altinfo_handle, [[maybe_unused]] TSEvent event)
{
  TSMBuffer hdr_buf;
  TSMLoc    hdr_loc;

  assert(event == TS_EVENT_HTTP_SELECT_ALT);

  TSHttpAltInfoClientReqGet(altinfo_handle, &hdr_buf, &hdr_loc);
  const Request clientReq(hdr_buf, hdr_loc); // no MLocRelease needed

  TSHttpAltInfoCachedReqGet(altinfo_handle, &hdr_buf, &hdr_loc);
  const Request cachedReq(hdr_buf, hdr_loc); // no MLocRelease needed

  TSHttpAltInfoCachedRespGet(altinfo_handle, &hdr_buf, &hdr_loc);
  Response cachedResp;
  cachedResp.init(hdr_buf, hdr_loc); // no MLocRelease needed

  plugin->handleSelectAlt(clientReq, cachedReq, cachedResp);
}

std::string
utils::internal::consumeFromTSIOBufferReader(TSIOBufferReader reader)
{
  std::string str;
  int         avail = TSIOBufferReaderAvail(reader);

  if (avail != TS_ERROR) {
    int consumed = 0;
    if (avail > 0) {
      str.reserve(avail + 1);

      int64_t         data_len;
      const char     *char_data;
      TSIOBufferBlock block = TSIOBufferReaderStart(reader);
      while (block != nullptr) {
        char_data = TSIOBufferBlockReadStart(block, reader, &data_len);
        str.append(char_data, data_len);
        consumed += data_len;
        block     = TSIOBufferBlockNext(block);
      }
    }
    TSIOBufferReaderConsume(reader, consumed);
  } else {
    LOG_ERROR("TSIOBufferReaderAvail returned error code %d for reader %p", avail, reader);
  }

  return str;
}

HttpVersion
utils::internal::getHttpVersion(TSMBuffer hdr_buf, TSMLoc hdr_loc)
{
  int version = TSHttpHdrVersionGet(hdr_buf, hdr_loc);
  if (version != TS_ERROR) {
    if ((TS_HTTP_MAJOR(version) == 0) && (TS_HTTP_MINOR(version) == 0)) {
      return HTTP_VERSION_0_9;
    }
    if ((TS_HTTP_MAJOR(version) == 1) && (TS_HTTP_MINOR(version) == 0)) {
      return HTTP_VERSION_1_0;
    }
    if ((TS_HTTP_MAJOR(version) == 1) && (TS_HTTP_MINOR(version) == 1)) {
      return HTTP_VERSION_1_1;
    } else {
      LOG_ERROR("Unrecognized version %d", version);
    }
  } else {
    LOG_ERROR("Could not get version; hdr_buf %p, hdr_loc %p", hdr_buf, hdr_loc);
  }
  return HTTP_VERSION_UNKNOWN;
}

void
utils::internal::initTransactionManagement()
{
  static pthread_once_t setup_pthread_once_control = PTHREAD_ONCE_INIT;
  pthread_once(&setup_pthread_once_control, setupTransactionManagement);
}
