/** @file

  A brief file description

  @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 <cstdint>

#include "gzip.h"
#include <zlib.h>

#include "Utils.h"

using namespace EsiLib;
using std::string;

template <typename T>
inline void
append(string &out, T data)
{
  for (unsigned int i = 0; i < sizeof(data); ++i) {
    out += static_cast<char>(data & 0xff);
    data = data >> 8;
  }
}

template <typename T>
inline void
extract(const char *in, T &data)
{
  data = 0;
  for (int i = (sizeof(data) - 1); i >= 0; --i) {
    data = data << 8;
    data = data | static_cast<unsigned char>(*(in + i));
  }
}

inline int
runDeflateLoop(z_stream &zstrm, int flush, std::string &cdata)
{
  char buf[BUF_SIZE];
  int deflate_result = Z_OK;
  do {
    zstrm.next_out  = reinterpret_cast<Bytef *>(buf);
    zstrm.avail_out = BUF_SIZE;
    deflate_result  = deflate(&zstrm, flush);
    if ((deflate_result == Z_OK) || (deflate_result == Z_STREAM_END)) {
      cdata.append(buf, BUF_SIZE - zstrm.avail_out);
      if ((deflate_result == Z_STREAM_END) || zstrm.avail_out) {
        break;
      }
    } else {
      break;
    }
  } while (true);
  return deflate_result;
}

bool
EsiLib::gzip(const ByteBlockList &blocks, std::string &cdata)
{
  cdata.assign(GZIP_HEADER_SIZE, 0); // reserving space for the header
  z_stream zstrm;
  zstrm.zalloc = Z_NULL;
  zstrm.zfree  = Z_NULL;
  zstrm.opaque = Z_NULL;
  if (deflateInit2(&zstrm, COMPRESSION_LEVEL, Z_DEFLATED, -MAX_WBITS, ZLIB_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
    Utils::ERROR_LOG("[%s] deflateInit2 failed!", __FUNCTION__);
    return false;
  }

  int total_data_len = 0;
  uLong crc          = crc32(0, Z_NULL, 0);
  int deflate_result = Z_OK;
  int in_data_size   = 0;
  for (auto block : blocks) {
    if (block.data && (block.data_len > 0)) {
      zstrm.next_in  = reinterpret_cast<Bytef *>(const_cast<char *>(block.data));
      zstrm.avail_in = block.data_len;
      in_data_size += block.data_len;
      deflate_result = runDeflateLoop(zstrm, 0, cdata);
      if (deflate_result != Z_OK) {
        break; // break out of the blocks iteration
      }
      crc = crc32(crc, reinterpret_cast<const Bytef *>(block.data), block.data_len);
      total_data_len += block.data_len;
    }
  }
  if (!in_data_size) {
    zstrm.avail_in = 0; // required for the "finish" loop as no data has been given so far
  }
  if (deflate_result == Z_OK) {
    deflate_result = runDeflateLoop(zstrm, Z_FINISH, cdata);
  }
  deflateEnd(&zstrm);
  if (deflate_result != Z_STREAM_END) {
    Utils::ERROR_LOG("[%s] Failure while deflating; error code %d", __FUNCTION__, deflate_result);
    return false;
  }
  cdata[0] = MAGIC_BYTE_1;
  cdata[1] = MAGIC_BYTE_2;
  cdata[2] = Z_DEFLATED;
  cdata[9] = OS_TYPE;
  append(cdata, static_cast<uint32_t>(crc));
  append(cdata, static_cast<int32_t>(total_data_len));
  return true;
}

bool
EsiLib::gunzip(const char *data, int data_len, BufferList &buf_list)
{
  if (!data || (data_len <= (GZIP_HEADER_SIZE + GZIP_TRAILER_SIZE))) {
    Utils::ERROR_LOG("[%s] Invalid arguments: 0x%p, %d", __FUNCTION__, data, data_len);
    return false;
  }
  if ((data[0] != MAGIC_BYTE_1) || (data[1] != MAGIC_BYTE_2) || (data[2] != Z_DEFLATED)) {
    Utils::ERROR_LOG("[%s] Header check failed!", __FUNCTION__);
    return false;
  }
  data += GZIP_HEADER_SIZE;
  data_len -= (GZIP_HEADER_SIZE + GZIP_TRAILER_SIZE);
  buf_list.clear();
  z_stream zstrm;
  zstrm.zalloc   = Z_NULL;
  zstrm.zfree    = Z_NULL;
  zstrm.opaque   = Z_NULL;
  zstrm.next_in  = nullptr;
  zstrm.avail_in = 0;
  if (inflateInit2(&zstrm, -MAX_WBITS) != Z_OK) {
    Utils::ERROR_LOG("[%s] inflateInit2 failed!", __FUNCTION__);
    return false;
  }
  zstrm.next_in  = reinterpret_cast<Bytef *>(const_cast<char *>(data));
  zstrm.avail_in = data_len;
  char raw_buf[BUF_SIZE];
  int inflate_result;
  int32_t unzipped_data_size = 0;
  int32_t curr_buf_size;
  uLong crc = crc32(0, Z_NULL, 0);
  do {
    zstrm.next_out  = reinterpret_cast<Bytef *>(raw_buf);
    zstrm.avail_out = BUF_SIZE;
    inflate_result  = inflate(&zstrm, Z_SYNC_FLUSH);
    curr_buf_size   = -1;
    if ((inflate_result == Z_OK) || (inflate_result == Z_BUF_ERROR)) {
      curr_buf_size = BUF_SIZE;
    } else if (inflate_result == Z_STREAM_END) {
      curr_buf_size = BUF_SIZE - zstrm.avail_out;
    }
    if (curr_buf_size > BUF_SIZE) {
      Utils::ERROR_LOG("[%s] buf too large", __FUNCTION__);
      break;
    }
    if (curr_buf_size < 1) {
      Utils::ERROR_LOG("[%s] buf below zero", __FUNCTION__);
      break;
    }
    unzipped_data_size += curr_buf_size;
    crc = crc32(crc, reinterpret_cast<const Bytef *>(raw_buf), curr_buf_size);

    // push empty object onto list and add data to in-list object to
    // avoid data copy for temporary
    buf_list.push_back(string());
    string &curr_buf = buf_list.back();
    curr_buf.assign(raw_buf, curr_buf_size);

    if (inflate_result == Z_STREAM_END) {
      break;
    }
  } while (zstrm.avail_in > 0);
  inflateEnd(&zstrm);
  if (inflate_result != Z_STREAM_END) {
    Utils::ERROR_LOG("[%s] Failure while inflating; error code %d", __FUNCTION__, inflate_result);
    return false;
  }
  int32_t orig_size;
  uint32_t orig_crc;
  extract(data + data_len, orig_crc);
  extract(data + data_len + 4, orig_size);
  if ((crc != orig_crc) || (unzipped_data_size != orig_size)) {
    Utils::ERROR_LOG("[%s] CRC/size error. Expecting (CRC, size) (0x%x, 0x%x); computed (0x%x, 0x%x)", __FUNCTION__, orig_crc,
                     orig_size, crc, unzipped_data_size);
    return false;
  }
  return true;
}
