/*
  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 plugin.cc
 * @brief traffic server plugin entry points.
 */

#include "ts/ts.h"
#include "ts/remap.h"
#include "cachekey.h"
#include "common.h"

/* Configuration only used by the global plugin instance. */
std::unique_ptr<Configs> globalConfig = nullptr;

/**
 * @brief Set the cache key called by both global and remap instances.
 *
 * @param txn transaction handle
 * @param config cachekey configuration
 */
static void
setCacheKey(TSHttpTxn txn, Configs *config, TSRemapRequestInfo *rri = nullptr)
{
  const CacheKeyKeyTypeSet &keyTypes = config->getKeyType();

  for (auto type : keyTypes) {
    /* Initial cache key facility from the requested URL. */
    CacheKey cachekey(txn, config->getSeparator(), config->getUriType(), type, rri);

    /* Don't use cachekey if not initialized properly */
    if (!cachekey.isValid()) {
      continue;
    }

    /* Append custom prefix or the host:port */
    if (!config->prefixToBeRemoved()) {
      cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri, config->canonicalPrefix());
    }
    /* Classify User-Agent and append the class name to the cache key if matched. */
    cachekey.appendUaClass(config->_classifier);

    /* Capture from User-Agent header. */
    cachekey.appendUaCaptures(config->_uaCapture);

    /* Append headers to the cache key. */
    cachekey.appendHeaders(config->_headers);

    /* Append cookies to the cache key. */
    cachekey.appendCookies(config->_cookies);

    /* Append the path to the cache key. */
    if (!config->pathToBeRemoved()) {
      cachekey.appendPath(config->_pathCapture, config->_pathCaptureUri);
    }
    /* Append query parameters to the cache key. */
    cachekey.appendQuery(config->_query);

    /* Set the cache key */
    cachekey.finalize();
  }
}

static int
contSetCachekey(TSCont /* contp ATS_UNUSED */, TSEvent /* event ATS_UNUSED */, void *edata)
{
  TSHttpTxn txn = static_cast<TSHttpTxn>(edata);

  setCacheKey(txn, globalConfig.get());

  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
  return 0;
}

/**
 * @brief Global plugin instance initialization.
 *
 * Processes the configuration and initializes a global plugin instance.
 * @param argc plugin arguments number
 * @param argv plugin arguments
 */
void
TSPluginInit(int argc, const char *argv[])
{
  TSPluginRegistrationInfo info;

  info.plugin_name   = PLUGIN_NAME;
  info.vendor_name   = "Apache Software Foundation";
  info.support_email = "dev@trafficserver.apache.org";

  if (TSPluginRegister(&info) != TS_SUCCESS) {
    CacheKeyError("global plugin registration failed");
  }

  globalConfig = std::make_unique<Configs>();
  if (nullptr != globalConfig && globalConfig->init(argc, argv, /* perRemapConfig */ false)) {
    TSCont cont = TSContCreate(contSetCachekey, nullptr);
    TSHttpHookAdd(TS_HTTP_POST_REMAP_HOOK, cont);

    CacheKeyDebug("global plugin initialized");
  } else {
    globalConfig.reset();

    CacheKeyError("failed to initialize global plugin");
  }
}

/**
 * @brief Plugin initialization.
 * @param apiInfo remap interface info pointer
 * @param errBuf error message buffer
 * @param errBufSize error message buffer size
 * @return always TS_SUCCESS.
 */
TSReturnCode
TSRemapInit(TSRemapInterface * /* apiInfo ATS_UNUSED */, char * /* errBuf ATS_UNUSED */, int /* erroBufSize ATS_UNUSED */)
{
  return TS_SUCCESS;
}

/**
 * @brief Plugin new instance entry point.
 *
 * Processes the configuration and initializes the plugin instance.
 * @param argc plugin arguments number
 * @param argv plugin arguments
 * @param instance new plugin instance pointer (initialized in this function)
 * @param errBuf error message buffer
 * @param errBufSize error message buffer size
 * @return TS_SUCCES if success or TS_ERROR if failure
 */
TSReturnCode
TSRemapNewInstance(int argc, char *argv[], void **instance, char * /* errBuf ATS_UNUSED */, int /* errBufSize ATS_UNUSED */)
{
  Configs *config = new Configs();
  if (nullptr != config && config->init(argc, const_cast<const char **>(argv), /* perRemapConfig */ true)) {
    *instance = config;
  } else {
    CacheKeyError("failed to initialize the remap plugin");
    *instance = nullptr;
    delete config;
    return TS_ERROR;
  }

  CacheKeyDebug("remap plugin initialized");
  return TS_SUCCESS;
}

/**
 * @brief Plugin instance deletion clean-up entry point.
 * @param plugin instance pointer.
 */
void
TSRemapDeleteInstance(void *instance)
{
  Configs *config = static_cast<Configs *>(instance);
  delete config;
}

/**
 * @brief Sets the cache key during the remap.
 *
 * Remap is never done, continue with next in chain.
 * @param instance plugin instance pointer
 * @param txn transaction handle
 * @param rri remap request info pointer
 * @return always TSREMAP_NO_REMAP
 */
TSRemapStatus
TSRemapDoRemap(void *instance, TSHttpTxn txn, TSRemapRequestInfo *rri)
{
  Configs *config = static_cast<Configs *>(instance);

  if (nullptr != config) {
    setCacheKey(txn, config, rri);
  }

  return TSREMAP_NO_REMAP;
}
