/** @file

  Transforms content using gzip, deflate or brotli

  @section license License

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

#include "ts/ts.h"
#include "tscore/ink_defs.h"
#include "tscpp/util/TextView.h"

#include "misc.h"
#include <cstring>
#include <cinttypes>
#include "debug_macros.h"

voidpf
gzip_alloc(voidpf /* opaque ATS_UNUSED */, uInt items, uInt size)
{
  return static_cast<voidpf>(TSmalloc(items * size));
}

void
gzip_free(voidpf /* opaque ATS_UNUSED */, voidpf address)
{
  TSfree(address);
}

namespace
{
// Strips parameters from value.  Returns cleared TextView if a q=f parameter present, where f is less than or equal to
// zero.
//
void
strip_ae_value(ts::TextView &value)
{
  ts::TextView compression{value.take_prefix_at(';')};
  compression.trim(" \t");
  while (value) {
    ts::TextView param{value.take_prefix_at(';')};
    ts::TextView name{param.take_prefix_at('=')};
    name.trim(" \t");
    if (strcasecmp("q", name) == 0) {
      // If q value is valid and is zero, suppress compression types.
      param.trim(" \t");
      if (param) {
        ts::TextView whole{param.take_prefix_at('.')};
        whole.ltrim(" \t");
        if ("0" == whole) {
          param.trim('0');
          if (!param) {
            // Suppress compression type.
            compression.clear();
            break;
          }
        }
      }
    }
  }
  value = compression;
}
} // end anonymous namespace

void
normalize_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc)
{
  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
  bool deflate = false;
  bool gzip    = false;
  bool br      = false;
  // remove the accept encoding field(s),
  // while finding out if gzip or deflate is supported.
  while (field) {
    int val_len;
    const char *values_ = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field, -1, &val_len);
    if (values_ && val_len) {
      ts::TextView values(values_, val_len);
      while (values) {
        ts::TextView next{values.take_prefix_at(',')};
        strip_ae_value(next);
        if (strcasecmp("gzip", next) == 0) {
          gzip = true;
        } else if (strcasecmp("br", next) == 0) {
          br = true;
        } else if (strcasecmp("deflate", next) == 0) {
          deflate = true;
        }
      }
    }

    TSMLoc tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
    TSMimeHdrFieldDestroy(reqp, hdr_loc, field); // catch retval?
    TSHandleMLocRelease(reqp, hdr_loc, field);
    field = tmp;
  }

  // append a new accept-encoding field in the header
  if (deflate || gzip || br) {
    TSMimeHdrFieldCreate(reqp, hdr_loc, &field);
    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
    if (br) {
      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "br", strlen("br"));
      info("normalized accept encoding to br");
    }
    if (gzip) {
      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "gzip", strlen("gzip"));
      info("normalized accept encoding to gzip");
    } else if (deflate) {
      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "deflate", strlen("deflate"));
      info("normalized accept encoding to deflate");
    }

    TSMimeHdrFieldAppend(reqp, hdr_loc, field);
    TSHandleMLocRelease(reqp, hdr_loc, field);
  }
}

void
hide_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc, const char *hidden_header_name)
{
  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
  while (field) {
    TSMLoc tmp;
    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, hidden_header_name, -1);
    TSHandleMLocRelease(reqp, hdr_loc, field);
    field = tmp;
  }
}

void
restore_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc, const char *hidden_header_name)
{
  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, hidden_header_name, -1);

  while (field) {
    TSMLoc tmp;
    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
    TSHandleMLocRelease(reqp, hdr_loc, field);
    field = tmp;
  }
}

const char *
init_hidden_header_name()
{
  char *hidden_header_name;
  const char *var_name = "proxy.config.proxy_name";
  TSMgmtString result;

  if (TSMgmtStringGet(var_name, &result) != TS_SUCCESS) {
    fatal("failed to get server name");
  } else {
    int hidden_header_name_len                 = strlen("x-accept-encoding-") + strlen(result);
    hidden_header_name                         = static_cast<char *>(TSmalloc(hidden_header_name_len + 1));
    hidden_header_name[hidden_header_name_len] = 0;
    sprintf(hidden_header_name, "x-accept-encoding-%s", result);
  }
  return hidden_header_name;
}

int
register_plugin()
{
  TSPluginRegistrationInfo info;

  info.plugin_name   = (char *)"compress";
  info.vendor_name   = (char *)"Apache Software Foundation";
  info.support_email = (char *)"dev@trafficserver.apache.org";

  if (TSPluginRegister(&info) != TS_SUCCESS) {
    return 0;
  }
  return 1;
}

void
log_compression_ratio(int64_t in, int64_t out)
{
  if (in) {
    info("Compressed size %" PRId64 " (bytes), Original size %" PRId64 ", ratio: %f", out, in, ((float)(in - out) / in));
  } else {
    debug("Compressed size %" PRId64 " (bytes), Original size %" PRId64 ", ratio: %f", out, in, 0.0F);
  }
}
