/*
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 3-Clause Clear License
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
 * License was not distributed with this source code in the LICENSE file, you
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
 * Alliance for Open Media Patent License 1.0 was not distributed with this
 * source code in the PATENTS file, you can obtain it at
 * aomedia.org/license/patent-license/.
 */

#include <assert.h>

#include "config/avm_config.h"

#include "avm_dsp/bitreader_buffer.h"
#include "avm_dsp/recenter.h"
#include "avm_ports/bitops.h"

size_t avm_rb_bytes_read(const struct avm_read_bit_buffer *rb) {
  return (rb->bit_offset + 7) >> 3;
}

int avm_rb_read_bit(struct avm_read_bit_buffer *rb) {
  const uint32_t off = rb->bit_offset;
  const uint32_t p = off >> 3;
  const int q = 7 - (int)(off & 0x7);
  if (rb->bit_buffer + p < rb->bit_buffer_end) {
    const int bit = (rb->bit_buffer[p] >> q) & 1;
    rb->bit_offset = off + 1;
    return bit;
  } else {
    if (rb->error_handler) {
      rb->error_handler(rb->error_handler_data, AVM_CODEC_CORRUPT_FRAME,
                        "Truncated packet");
    }
    return 0;
  }
}

int avm_rb_read_literal(struct avm_read_bit_buffer *rb, int bits) {
  assert(bits <= 31);
  int value = 0, bit;
  for (bit = bits - 1; bit >= 0; bit--) value |= avm_rb_read_bit(rb) << bit;
  return value;
}

uint32_t avm_rb_read_unsigned_literal(struct avm_read_bit_buffer *rb,
                                      int bits) {
  assert(bits <= 32);
  uint32_t value = 0;
  int bit;
  for (bit = bits - 1; bit >= 0; bit--)
    value |= (uint32_t)avm_rb_read_bit(rb) << bit;
  return value;
}

int avm_rb_read_inv_signed_literal(struct avm_read_bit_buffer *rb, int bits) {
  const int nbits = sizeof(unsigned) * 8 - bits - 1;
  const unsigned value = (unsigned)avm_rb_read_literal(rb, bits + 1) << nbits;
  return ((int)value) >> nbits;
}

uint32_t avm_rb_read_uvlc(struct avm_read_bit_buffer *rb) {
  int leading_zeros = 0;
  while (leading_zeros < 32 && !avm_rb_read_bit(rb)) ++leading_zeros;
  // Maximum 32 bits.
  if (leading_zeros == 32) {
    if (rb->error_handler) {
      rb->error_handler(rb->error_handler_data, AVM_CODEC_CORRUPT_FRAME,
                        "VLC input too long (more than 31 leading zeros)");
    }
    return UINT32_MAX;  // Error.
  }
  const uint32_t base = (1u << leading_zeros) - 1;
  const uint32_t value = avm_rb_read_literal(rb, leading_zeros);
  return base + value;
}

int32_t avm_rb_read_svlc(struct avm_read_bit_buffer *rb) {
  const uint32_t value = avm_rb_read_uvlc(rb);
  if (value == UINT32_MAX) return INT32_MIN;  // Error.
  const int32_t ceil_half = (int32_t)((value + 1) / 2);
  return (value % 2) ? ceil_half : -ceil_half;
}

uint16_t avm_rb_read_primitive_quniform(struct avm_read_bit_buffer *rb,
                                        uint16_t n) {
  if (n <= 1) return 0;
  const int l = get_msb(n) + 1;
  const int m = (1 << l) - n;
  const int v = avm_rb_read_literal(rb, l - 1);
  return v < m ? v : (v << 1) - m + avm_rb_read_bit(rb);
}

uint16_t avm_rb_read_primitive_ref_quniform(struct avm_read_bit_buffer *rb,
                                            uint16_t n, uint16_t r) {
  if (avm_rb_read_bit(rb)) {  // unequal
    int v = avm_rb_read_primitive_quniform(rb, n - 1);
    v += (v >= r);
    return v;
  } else {
    return r;
  }
}

static uint16_t avm_rb_read_primitive_subexpfin(struct avm_read_bit_buffer *rb,
                                                uint16_t n, uint16_t k) {
  int i = 0;
  int mk = 0;

  while (1) {
    int b = (i ? k + i - 1 : k);
    int a = (1 << b);

    if (n <= mk + 3 * a) {
      return avm_rb_read_primitive_quniform(rb, n - mk) + mk;
    }

    if (!avm_rb_read_bit(rb)) {
      return avm_rb_read_literal(rb, b) + mk;
    }

    i = i + 1;
    mk += a;
  }

  assert(0);
  return 0;
}

uint16_t avm_rb_read_primitive_refsubexpfin(struct avm_read_bit_buffer *rb,
                                            uint16_t n, uint16_t k,
                                            uint16_t ref) {
  assert(ref < n);
  return inv_recenter_finite_nonneg(n, ref,
                                    avm_rb_read_primitive_subexpfin(rb, n, k));
}

int16_t avm_rb_read_signed_primitive_refsubexpfin(
    struct avm_read_bit_buffer *rb, uint16_t n, uint16_t k, int16_t ref) {
  assert(n > 0);
  const uint16_t offset = n - 1;
  const uint16_t scaled_n = (n << 1) - 1;
  return avm_rb_read_primitive_refsubexpfin(rb, scaled_n, k, ref + offset) -
         offset;
}

// implementation of leb128() signaling in the specification using
// avm_read_bit_buffer
uint32_t avm_rb_read_uleb(struct avm_read_bit_buffer *rb) {
  if (rb->bit_offset % 8 != 0) {
    if (rb->error_handler) {
      rb->error_handler(rb->error_handler_data, AVM_CODEC_ERROR,
                        "leb128() is not byte aligned");
    }
    return 0;
  }
  uint64_t value = 0;
  for (size_t i = 0; i < 8; ++i) {
    uint64_t byte = avm_rb_read_literal(rb, 8);
    value |= ((byte & 0x7f) << (i * 7));
    if (!(byte & 0x80)) {
      if (value > UINT32_MAX) {
        if (rb->error_handler) {
          rb->error_handler(rb->error_handler_data, AVM_CODEC_CORRUPT_FRAME,
                            "leb128() value greater than UINT32_MAX");
        }
        return 0;
      }
      return (uint32_t)value;
    }
  }
  if (rb->error_handler) {
    rb->error_handler(rb->error_handler_data, AVM_CODEC_CORRUPT_FRAME,
                      "leb128() input longer than 8 bytes");
  }
  return 0;
}

uint32_t avm_rb_read_rice_golomb(struct avm_read_bit_buffer *rb, int k) {
  // The maximum of k is related to the maximum of quotient.
  assert(k <= 26);
  uint32_t value = 0;
  uint32_t quotient = 0;
  uint32_t remainder = 0;
  uint32_t M = 1 << k;

  // To defend against invalid inputs, impose a maximum of 31 on quotient. The
  // maximum of 31 (= 2^5 - 1) is somewhat arbitrary. In general it is
  // convenient to choose a maximum that is 2^q - 1 for some q < 31. Then we can
  // require k <= 31 - q.
  while (quotient < 32 && avm_rb_read_bit(rb) != 0) quotient++;
  if (quotient == 32) {
    if (rb->error_handler) {
      rb->error_handler(rb->error_handler_data, AVM_CODEC_CORRUPT_FRAME,
                        "Rice Golomb coding too long (quotient >= 32)");
    }
    return UINT32_MAX;  // Error.
  }
  remainder = avm_rb_read_unsigned_literal(rb, k);
  // value <= 2^31 - 1 if k <= 26, so there is no risk of overflow.
  value = quotient * M + remainder;
  return value;
}
