/*
 *
 * Copyright 2018 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 "src/core/tsi/alts/handshaker/transport_security_common_api.h"

bool grpc_gcp_rpc_protocol_versions_set_max(
    grpc_gcp_rpc_protocol_versions* versions, uint32_t max_major,
    uint32_t max_minor) {
  if (versions == nullptr) {
    gpr_log(GPR_ERROR,
            "versions is nullptr in "
            "grpc_gcp_rpc_protocol_versions_set_max().");
    return false;
  }
  versions->has_max_rpc_version = true;
  versions->max_rpc_version.has_major = true;
  versions->max_rpc_version.has_minor = true;
  versions->max_rpc_version.major = max_major;
  versions->max_rpc_version.minor = max_minor;
  return true;
}

bool grpc_gcp_rpc_protocol_versions_set_min(
    grpc_gcp_rpc_protocol_versions* versions, uint32_t min_major,
    uint32_t min_minor) {
  if (versions == nullptr) {
    gpr_log(GPR_ERROR,
            "versions is nullptr in "
            "grpc_gcp_rpc_protocol_versions_set_min().");
    return false;
  }
  versions->has_min_rpc_version = true;
  versions->min_rpc_version.has_major = true;
  versions->min_rpc_version.has_minor = true;
  versions->min_rpc_version.major = min_major;
  versions->min_rpc_version.minor = min_minor;
  return true;
}

size_t grpc_gcp_rpc_protocol_versions_encode_length(
    const grpc_gcp_rpc_protocol_versions* versions) {
  if (versions == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to "
            "grpc_gcp_rpc_protocol_versions_encode_length().");
    return 0;
  }
  pb_ostream_t size_stream;
  memset(&size_stream, 0, sizeof(pb_ostream_t));
  if (!pb_encode(&size_stream, grpc_gcp_RpcProtocolVersions_fields, versions)) {
    gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream));
    return 0;
  }
  return size_stream.bytes_written;
}

bool grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes(
    const grpc_gcp_rpc_protocol_versions* versions, uint8_t* bytes,
    size_t bytes_length) {
  if (versions == nullptr || bytes == nullptr || bytes_length == 0) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to "
            "grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes().");
    return false;
  }
  pb_ostream_t output_stream = pb_ostream_from_buffer(bytes, bytes_length);
  if (!pb_encode(&output_stream, grpc_gcp_RpcProtocolVersions_fields,
                 versions)) {
    gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&output_stream));
    return false;
  }
  return true;
}

bool grpc_gcp_rpc_protocol_versions_encode(
    const grpc_gcp_rpc_protocol_versions* versions, grpc_slice* slice) {
  if (versions == nullptr || slice == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to "
            "grpc_gcp_rpc_protocol_versions_encode().");
    return false;
  }
  size_t encoded_length =
      grpc_gcp_rpc_protocol_versions_encode_length(versions);
  if (encoded_length == 0) return false;
  *slice = grpc_slice_malloc(encoded_length);
  return grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes(
      versions, GRPC_SLICE_START_PTR(*slice), encoded_length);
}

bool grpc_gcp_rpc_protocol_versions_decode(
    grpc_slice slice, grpc_gcp_rpc_protocol_versions* versions) {
  if (versions == nullptr) {
    gpr_log(GPR_ERROR,
            "version is nullptr in "
            "grpc_gcp_rpc_protocol_versions_decode().");
    return false;
  }
  pb_istream_t stream = pb_istream_from_buffer(GRPC_SLICE_START_PTR(slice),
                                               GRPC_SLICE_LENGTH(slice));
  if (!pb_decode(&stream, grpc_gcp_RpcProtocolVersions_fields, versions)) {
    gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
    return false;
  }
  return true;
}

bool grpc_gcp_rpc_protocol_versions_copy(
    const grpc_gcp_rpc_protocol_versions* src,
    grpc_gcp_rpc_protocol_versions* dst) {
  if ((src == nullptr && dst != nullptr) ||
      (src != nullptr && dst == nullptr)) {
    gpr_log(GPR_ERROR,
            "Invalid arguments to "
            "grpc_gcp_rpc_protocol_versions_copy().");
    return false;
  }
  if (src == nullptr) {
    return true;
  }
  grpc_gcp_rpc_protocol_versions_set_max(dst, src->max_rpc_version.major,
                                         src->max_rpc_version.minor);
  grpc_gcp_rpc_protocol_versions_set_min(dst, src->min_rpc_version.major,
                                         src->min_rpc_version.minor);
  return true;
}

namespace grpc_core {
namespace internal {

int grpc_gcp_rpc_protocol_version_compare(
    const grpc_gcp_rpc_protocol_versions_version* v1,
    const grpc_gcp_rpc_protocol_versions_version* v2) {
  if ((v1->major > v2->major) ||
      (v1->major == v2->major && v1->minor > v2->minor)) {
    return 1;
  }
  if ((v1->major < v2->major) ||
      (v1->major == v2->major && v1->minor < v2->minor)) {
    return -1;
  }
  return 0;
}

}  // namespace internal
}  // namespace grpc_core

bool grpc_gcp_rpc_protocol_versions_check(
    const grpc_gcp_rpc_protocol_versions* local_versions,
    const grpc_gcp_rpc_protocol_versions* peer_versions,
    grpc_gcp_rpc_protocol_versions_version* highest_common_version) {
  if (local_versions == nullptr || peer_versions == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid arguments to "
            "grpc_gcp_rpc_protocol_versions_check().");
    return false;
  }
  /* max_common_version is MIN(local.max, peer.max) */
  const grpc_gcp_rpc_protocol_versions_version* max_common_version =
      grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
          &local_versions->max_rpc_version, &peer_versions->max_rpc_version) > 0
          ? &peer_versions->max_rpc_version
          : &local_versions->max_rpc_version;
  /* min_common_version is MAX(local.min, peer.min) */
  const grpc_gcp_rpc_protocol_versions_version* min_common_version =
      grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
          &local_versions->min_rpc_version, &peer_versions->min_rpc_version) > 0
          ? &local_versions->min_rpc_version
          : &peer_versions->min_rpc_version;
  bool result = grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
                    max_common_version, min_common_version) >= 0
                    ? true
                    : false;
  if (result && highest_common_version != nullptr) {
    memcpy(highest_common_version, max_common_version,
           sizeof(grpc_gcp_rpc_protocol_versions_version));
  }
  return result;
}
