/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed 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 <grpc/support/port_platform.h>

#include <stdlib.h>
#include <string.h>

#include <grpc/compression.h>

#include "src/core/lib/compression/algorithm_metadata.h"
#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/static_metadata.h"

int grpc_compression_algorithm_is_message(
    grpc_compression_algorithm algorithm) {
  return (algorithm >= GRPC_COMPRESS_DEFLATE && algorithm <= GRPC_COMPRESS_GZIP)
             ? 1
             : 0;
}

int grpc_compression_algorithm_is_stream(grpc_compression_algorithm algorithm) {
  return (algorithm == GRPC_COMPRESS_STREAM_GZIP) ? 1 : 0;
}

int grpc_compression_algorithm_parse(grpc_slice name,
                                     grpc_compression_algorithm* algorithm) {
  if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
    *algorithm = GRPC_COMPRESS_NONE;
    return 1;
  } else if (grpc_slice_eq(name, GRPC_MDSTR_DEFLATE)) {
    *algorithm = GRPC_COMPRESS_DEFLATE;
    return 1;
  } else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
    *algorithm = GRPC_COMPRESS_GZIP;
    return 1;
  } else if (grpc_slice_eq(name, GRPC_MDSTR_STREAM_SLASH_GZIP)) {
    *algorithm = GRPC_COMPRESS_STREAM_GZIP;
    return 1;
  } else {
    return 0;
  }
  return 0;
}

int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
                                    const char** name) {
  GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
                 ((int)algorithm, name));
  switch (algorithm) {
    case GRPC_COMPRESS_NONE:
      *name = "identity";
      return 1;
    case GRPC_COMPRESS_DEFLATE:
      *name = "deflate";
      return 1;
    case GRPC_COMPRESS_GZIP:
      *name = "gzip";
      return 1;
    case GRPC_COMPRESS_STREAM_GZIP:
      *name = "stream/gzip";
      return 1;
    case GRPC_COMPRESS_ALGORITHMS_COUNT:
      return 0;
  }
  return 0;
}

grpc_compression_algorithm grpc_compression_algorithm_for_level(
    grpc_compression_level level, uint32_t accepted_encodings) {
  grpc_compression_algorithm algo;
  if (level == GRPC_COMPRESS_LEVEL_NONE) {
    return GRPC_COMPRESS_NONE;
  } else if (level <= GRPC_COMPRESS_LEVEL_HIGH) {
    // TODO(mxyan): Design algorithm to select from all algorithms, including
    // stream compression algorithm
    if (!grpc_compression_algorithm_from_message_stream_compression_algorithm(
            &algo,
            grpc_message_compression_algorithm_for_level(
                level,
                grpc_compression_bitset_to_message_bitset(accepted_encodings)),
            static_cast<grpc_stream_compression_algorithm>(0))) {
      gpr_log(GPR_ERROR, "Parse compression level error");
      return GRPC_COMPRESS_NONE;
    }
    return algo;
  } else {
    gpr_log(GPR_ERROR, "Unknown compression level: %d", level);
    return GRPC_COMPRESS_NONE;
  }
}

void grpc_compression_options_init(grpc_compression_options* opts) {
  memset(opts, 0, sizeof(*opts));
  /* all enabled by default */
  opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
}

void grpc_compression_options_enable_algorithm(
    grpc_compression_options* opts, grpc_compression_algorithm algorithm) {
  GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
}

void grpc_compression_options_disable_algorithm(
    grpc_compression_options* opts, grpc_compression_algorithm algorithm) {
  GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
}

int grpc_compression_options_is_algorithm_enabled(
    const grpc_compression_options* opts,
    grpc_compression_algorithm algorithm) {
  return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
}

grpc_slice grpc_compression_algorithm_slice(
    grpc_compression_algorithm algorithm) {
  switch (algorithm) {
    case GRPC_COMPRESS_NONE:
      return GRPC_MDSTR_IDENTITY;
    case GRPC_COMPRESS_DEFLATE:
      return GRPC_MDSTR_DEFLATE;
    case GRPC_COMPRESS_GZIP:
      return GRPC_MDSTR_GZIP;
    case GRPC_COMPRESS_STREAM_GZIP:
      return GRPC_MDSTR_STREAM_SLASH_GZIP;
    case GRPC_COMPRESS_ALGORITHMS_COUNT:
      return grpc_empty_slice();
  }
  return grpc_empty_slice();
}

grpc_compression_algorithm grpc_compression_algorithm_from_slice(
    grpc_slice str) {
  if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
  if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE)) return GRPC_COMPRESS_DEFLATE;
  if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_GZIP;
  if (grpc_slice_eq(str, GRPC_MDSTR_STREAM_SLASH_GZIP))
    return GRPC_COMPRESS_STREAM_GZIP;
  return GRPC_COMPRESS_ALGORITHMS_COUNT;
}

grpc_mdelem grpc_compression_encoding_mdelem(
    grpc_compression_algorithm algorithm) {
  switch (algorithm) {
    case GRPC_COMPRESS_NONE:
      return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
    case GRPC_COMPRESS_DEFLATE:
      return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
    case GRPC_COMPRESS_GZIP:
      return GRPC_MDELEM_GRPC_ENCODING_GZIP;
    case GRPC_COMPRESS_STREAM_GZIP:
      return GRPC_MDELEM_GRPC_ENCODING_GZIP;
    default:
      break;
  }
  return GRPC_MDNULL;
}
