// Copyright 2018 Google LLC
//
// 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
//
//     https://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 "src/decoder/intermediate_astc_block.h"
#include "src/decoder/integer_sequence_codec.h"
#include "src/base/bit_stream.h"
#include "src/base/math_utils.h"
#include "src/base/optional.h"
#include "src/base/uint128.h"

#include <algorithm>
#include <numeric>
#include <sstream>

namespace astc_codec {

namespace {

constexpr int kEndpointRange_ReturnInvalidWeightDims = -1;
constexpr int kEndpointRange_ReturnNotEnoughColorBits = -2;

base::UInt128 PackVoidExtentBlock(uint16_t r, uint16_t g, uint16_t b,
                                  uint16_t a, std::array<uint16_t, 4> coords) {
  base::BitStream<base::UInt128> bit_sink;

  // Put void extent mode...
  bit_sink.PutBits(0xDFC, 12);

  // Each of the coordinates goes in 13 bits at a time.
  for (auto coord : coords) {
    assert(coord < 1 << 13);
    bit_sink.PutBits(coord, 13);
  }
  assert(bit_sink.Bits() == 64);

  // Then we add R, G, B, and A in order
  bit_sink.PutBits(r, 16);
  bit_sink.PutBits(g, 16);
  bit_sink.PutBits(b, 16);
  bit_sink.PutBits(a, 16);

  assert(bit_sink.Bits() == 128);

  base::UInt128 result;
  bit_sink.GetBits(128, &result);
  return result;
}

base::Optional<std::string> GetEncodedWeightRange(int range,
                                                  std::array<int, 3>* const r) {
  const std::array<std::array<int, 3>, 12> kValidRangeEncodings =
      {{ {{ 0, 1, 0 }}, {{ 1, 1, 0 }}, {{ 0, 0, 1 }},
         {{ 1, 0, 1 }}, {{ 0, 1, 1 }}, {{ 1, 1, 1 }},
         {{ 0, 1, 0 }}, {{ 1, 1, 0 }}, {{ 0, 0, 1 }},
         {{ 1, 0, 1 }}, {{ 0, 1, 1 }}, {{ 1, 1, 1 }} }};

  // If our range is larger than all available ranges, this is an error.
  const int smallest_range = kValidWeightRanges.front();
  const int largest_range = kValidWeightRanges.back();
  if (range < smallest_range || largest_range < range) {
    std::stringstream strm;
    strm << "Could not find block mode. Invalid weight range: "
         << range << " not in [" << smallest_range << ", "
         << largest_range << std::endl;
    return strm.str();
  }

  // Find the upper bound on the range, otherwise.
  const auto range_iter = std::lower_bound(
      kValidWeightRanges.cbegin(), kValidWeightRanges.cend(), range);
  auto enc_iter = kValidRangeEncodings.cbegin();
  enc_iter += std::distance(kValidWeightRanges.cbegin(), range_iter);
  *r = *enc_iter;
  return {};
}

struct BlockModeInfo {
  int min_weight_grid_dim_x;
  int max_weight_grid_dim_x;
  int min_weight_grid_dim_y;
  int max_weight_grid_dim_y;
  int r0_bit_pos;
  int r1_bit_pos;
  int r2_bit_pos;
  int weight_grid_x_offset_bit_pos;
  int weight_grid_y_offset_bit_pos;
  bool require_single_plane_low_prec;
};

constexpr int kNumBlockModes = 10;
const std::array<BlockModeInfo, kNumBlockModes> kBlockModeInfo {{
  { 4, 7, 2, 5, 4, 0, 1, 7, 5, false },      // B+4 A+2
  { 8, 11, 2, 5, 4, 0, 1, 7, 5, false },     // B+8 A+2
  { 2, 5, 8, 11, 4, 0, 1, 5, 7, false },     // A+2 B+8
  { 2, 5, 6, 7, 4, 0, 1, 5, 7, false },      // A+2 B+6
  { 2, 3, 2, 5, 4, 0, 1, 7, 5, false },      // B+2 A+2
  { 12, 12, 2, 5, 4, 2, 3, -1, 5, false },   // 12  A+2
  { 2, 5, 12, 12, 4, 2, 3, 5, -1, false },   // A+2 12
  { 6, 6, 10, 10, 4, 2, 3, -1, -1, false },  // 6   10
  { 10, 10, 6, 6, 4, 2, 3, -1, -1, false },  // 10  6
  { 6, 9, 6, 9, 4, 2, 3, 5, 9, true }        // A+6 B+6
}};

// These are the bits that must be set for ASTC to recognize a given
// block mode. They are the 1's set in table C.2.8 of the spec.
const std::array<int, kNumBlockModes> kBlockModeMask = {{
  0x0, 0x4, 0x8, 0xC, 0x10C, 0x0, 0x80, 0x180, 0x1A0, 0x100
}};

static base::Optional<std::string> PackBlockMode(int dim_x, int dim_y, int range,
                                          bool dual_plane,
                                          base::BitStream<base::UInt128>* const bit_sink) {
  // We need to set the high precision bit if our range is too high...
  bool high_prec = range > 7;

  std::array<int, 3> r;
  const auto result = GetEncodedWeightRange(range, &r);
  if (result) {
    return result;
  }

  // The high two bits of R must not be zero. If this happens then it's
  // an illegal encoding according to Table C.2.7 that should have gotten
  // caught in GetEncodedWeightRange
  assert((r[1] | r[2]) > 0);

  // Just go through the table and see if any of the modes can handle
  // the given dimensions.
  for (int mode = 0; mode < kNumBlockModes; ++mode) {
    const BlockModeInfo& block_mode = kBlockModeInfo[mode];

    bool is_valid_mode = true;
    is_valid_mode &= block_mode.min_weight_grid_dim_x <= dim_x;
    is_valid_mode &= dim_x <= block_mode.max_weight_grid_dim_x;
    is_valid_mode &= block_mode.min_weight_grid_dim_y <= dim_y;
    is_valid_mode &= dim_y <= block_mode.max_weight_grid_dim_y;
    is_valid_mode &= !(block_mode.require_single_plane_low_prec && dual_plane);
    is_valid_mode &= !(block_mode.require_single_plane_low_prec && high_prec);

    if (!is_valid_mode) {
      continue;
    }

    // Initialize to the bits we must set.
    uint32_t encoded_mode = kBlockModeMask[mode];
    auto setBit = [&encoded_mode](const uint32_t value, const uint32_t offset) {
      encoded_mode = (encoded_mode & ~(1 << offset)) | ((value & 1) << offset);
    };

    // Set all the bits we need to set
    setBit(r[0], block_mode.r0_bit_pos);
    setBit(r[1], block_mode.r1_bit_pos);
    setBit(r[2], block_mode.r2_bit_pos);

    // Find our width and height offset from the base width and height weight
    // grid dimension for the given block mode. These are the 1-2 bits that
    // get encoded in the block mode used to calculate the final weight grid
    // width and height.
    const int offset_x = dim_x - block_mode.min_weight_grid_dim_x;
    const int offset_y = dim_y - block_mode.min_weight_grid_dim_y;

    // If we don't have an offset position then our offset better be zero.
    // If this isn't the case, then this isn't a viable block mode and we
    // should have caught this sooner.
    assert(block_mode.weight_grid_x_offset_bit_pos >= 0 || offset_x == 0);
    assert(block_mode.weight_grid_y_offset_bit_pos >= 0 || offset_y == 0);

    encoded_mode |= offset_x << block_mode.weight_grid_x_offset_bit_pos;
    encoded_mode |= offset_y << block_mode.weight_grid_y_offset_bit_pos;

    if (!block_mode.require_single_plane_low_prec) {
      setBit(high_prec, 9);
      setBit(dual_plane, 10);
    }

    // Make sure that the mode is the first thing the bit sink is writing to
    assert(bit_sink->Bits() == 0);
    bit_sink->PutBits(encoded_mode, 11);

    return {};
  }

  return std::string("Could not find viable block mode");
}

// Returns true if all endpoint modes are equal.
bool SharedEndpointModes(const IntermediateBlockData& data) {
  return std::accumulate(
      data.endpoints.begin(), data.endpoints.end(), true,
      [&data](const bool& a, const IntermediateEndpointData& b) {
        return a && b.mode == data.endpoints[0].mode;
      });
}

// Returns the starting bit (between 0 and 128) where the extra CEM and
// dual plane info is stored in the ASTC block.
int ExtraConfigBitPosition(const IntermediateBlockData& data) {
  const bool has_dual_channel = data.dual_plane_channel.hasValue();
  const int num_weights = data.weight_grid_dim_x * data.weight_grid_dim_y *
      (has_dual_channel ? 2 : 1);
  const int num_weight_bits =
      IntegerSequenceCodec::GetBitCountForRange(num_weights, data.weight_range);

  int extra_config_bits = 0;
  if (!SharedEndpointModes(data)) {
    const int num_encoded_cem_bits = 2 + data.endpoints.size() * 3;
    extra_config_bits = num_encoded_cem_bits - 6;
  }

  if (has_dual_channel) {
    extra_config_bits += 2;
  }

  return 128 - num_weight_bits - extra_config_bits;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////

base::Optional<IntermediateBlockData> UnpackIntermediateBlock(
    const PhysicalASTCBlock& pb) {
  if (pb.IsIllegalEncoding()) {
    return {};
  }

  if (pb.IsVoidExtent()) {
    return {};
  }

  // Non void extent? Then let's try to decode everything else.
  IntermediateBlockData data;

  // All blocks have color values...
  const base::UInt128 color_bits_mask =
      (base::UInt128(1) << pb.NumColorBits().value()) - 1;
  const base::UInt128 color_bits =
      (pb.GetBlockBits() >> pb.ColorStartBit().value()) & color_bits_mask;
  base::BitStream<base::UInt128> bit_src(color_bits, 128);

  IntegerSequenceDecoder color_decoder(pb.ColorValuesRange().value());
  const int num_colors_in_block = pb.NumColorValues().value();
  std::vector<int> colors = color_decoder.Decode(num_colors_in_block, &bit_src);

  // Decode simple info
  const auto weight_dims = pb.WeightGridDims();
  data.weight_grid_dim_x = weight_dims->at(0);
  data.weight_grid_dim_y = weight_dims->at(1);
  data.weight_range = pb.WeightRange().value();

  data.partition_id = pb.PartitionID();
  data.dual_plane_channel = pb.DualPlaneChannel();

  auto colors_iter = colors.begin();
  for (int i = 0; i < pb.NumPartitions().value(); ++i) {
    IntermediateEndpointData ep_data;
    ep_data.mode = pb.GetEndpointMode(i).value();

    const int num_colors = NumColorValuesForEndpointMode(ep_data.mode);
    ep_data.colors.insert(ep_data.colors.end(), colors_iter,
                          colors_iter + num_colors);
    colors_iter += num_colors;

    data.endpoints.push_back(ep_data);
  }
  assert(colors_iter == colors.end());
  data.endpoint_range = pb.ColorValuesRange().value();

  // Finally decode the weights
  const base::UInt128 weight_bits_mask =
      (base::UInt128(1) << pb.NumWeightBits().value()) - 1;
  const base::UInt128 weight_bits =
      base::ReverseBits(pb.GetBlockBits()) & weight_bits_mask;
  bit_src = base::BitStream<base::UInt128>(weight_bits, 128);

  IntegerSequenceDecoder weight_decoder(data.weight_range);
  int num_weights = data.weight_grid_dim_x * data.weight_grid_dim_y;
  num_weights *= pb.IsDualPlane() ? 2 : 1;
  data.weights = weight_decoder.Decode(num_weights, &bit_src);

  return data;
}

int EndpointRangeForBlock(const IntermediateBlockData& data) {
  // First check to see if we exceed the number of bits allotted for weights, as
  // specified in C.2.24. If so, then the endpoint range is meaningless, but not
  // because we had an overzealous color endpoint mode, so return a different
  // error code.
  if (IntegerSequenceCodec::GetBitCountForRange(
          data.weight_grid_dim_x * data.weight_grid_dim_y *
          (data.dual_plane_channel.hasValue() ? 2 : 1),
          data.weight_range) > 96) {
    return kEndpointRange_ReturnInvalidWeightDims;
  }

  const int num_partitions = data.endpoints.size();

  // Calculate the number of bits that we would write prior to getting to the
  // color endpoint data
  const int bits_written =
      11   // Block mode
      + 2  // Num partitions
      + ((num_partitions > 1) ? 10 : 0)  // Partition ID
      + ((num_partitions == 1) ? 4 : 6);  // Shared CEM bits

  // We can determine the range based on how many bits we have between the start
  // of the color endpoint data and the next section, which is the extra config
  // bit position
  const int color_bits_available = ExtraConfigBitPosition(data) - bits_written;

  int num_color_values = 0;
  for (const auto& ep_data : data.endpoints) {
    num_color_values += NumColorValuesForEndpointMode(ep_data.mode);
  }

  // There's no way any valid ASTC encoding has no room left for any color
  // values. If we hit this then something is wrong in the caller -- abort.
  // According to section C.2.24, the smallest number of bits available is
  // ceil(13*C/5), where C is the number of color endpoint integers needed.
  const int bits_needed = (13 * num_color_values + 4) / 5;
  if (color_bits_available < bits_needed) {
    return kEndpointRange_ReturnNotEnoughColorBits;
  }

  int color_value_range = 255;
  for (; color_value_range > 1; --color_value_range) {
    const int bits_for_range = IntegerSequenceCodec::GetBitCountForRange(
        num_color_values, color_value_range);
    if (bits_for_range <= color_bits_available) {
      break;
    }
  }

  return color_value_range;
}

base::Optional<VoidExtentData> UnpackVoidExtent(const PhysicalASTCBlock& pb) {
  if (pb.IsIllegalEncoding()) {
    return {};
  }

  if (!pb.IsVoidExtent()) {
    return {};
  }

  // All blocks have color values...
  const base::UInt128 color_bits_mask =
      (base::UInt128(1) << pb.NumColorBits().value()) - 1;
  const uint64_t color_bits = (
      (pb.GetBlockBits() >> pb.ColorStartBit().value()) & color_bits_mask).LowBits();

  assert(pb.NumColorValues().value() == 4);
  VoidExtentData data;
  data.r = static_cast<uint16_t>((color_bits >>  0) & 0xFFFF);
  data.g = static_cast<uint16_t>((color_bits >> 16) & 0xFFFF);
  data.b = static_cast<uint16_t>((color_bits >> 32) & 0xFFFF);
  data.a = static_cast<uint16_t>((color_bits >> 48) & 0xFFFF);

  const auto void_extent_coords = pb.VoidExtentCoords();
  if (void_extent_coords) {
    data.coords[0] = void_extent_coords->at(0);
    data.coords[1] = void_extent_coords->at(1);
    data.coords[2] = void_extent_coords->at(2);
    data.coords[3] = void_extent_coords->at(3);
  } else {
    uint16_t all_ones = (1 << 13) - 1;
    for (auto& coord : data.coords) {
      coord = all_ones;
    }
  }

  return data;
}

// Packs the given intermediate block into a physical block. Returns false if
// the provided values in the intermediate block emit an illegal ASTC
// encoding.
base::Optional<std::string> Pack(const IntermediateBlockData& data,
                                 base::UInt128* pb) {
  if (data.weights.size() !=
      data.weight_grid_dim_x * data.weight_grid_dim_y *
      (data.dual_plane_channel.hasValue() ? 2 : 1)) {
    return std::string("Incorrect number of weights!");
  }

  // If it's not a void extent block, then it gets a bit more tricky...
  base::BitStream<base::UInt128> bit_sink;

  // First we need to encode the block mode.
  const auto error_string = PackBlockMode(
      data.weight_grid_dim_x, data.weight_grid_dim_y, data.weight_range,
      data.dual_plane_channel.hasValue(), &bit_sink);
  if (error_string) {
    return error_string;
  }

  // Next, we place the number of partitions minus one.
  const int num_partitions = data.endpoints.size();
  bit_sink.PutBits(num_partitions - 1, 2);

  // If we have more than one partition, then we also have a partition ID.
  if (num_partitions > 1) {
    const int id = data.partition_id.value();
    assert(id >= 0);
    bit_sink.PutBits(id, 10);
  }

  // Take a detour, let's encode the weights so that we know how many bits they
  // consume.
  base::BitStream<base::UInt128> weight_sink;

  IntegerSequenceEncoder weight_enc(data.weight_range);
  for (auto weight : data.weights) {
    weight_enc.AddValue(weight);
  }
  weight_enc.Encode(&weight_sink);

  const int num_weight_bits = weight_sink.Bits();
  assert(num_weight_bits ==
           IntegerSequenceCodec::GetBitCountForRange(
               data.weights.size(), data.weight_range));

  // Let's continue... how much after the color data do we need to write?
  int extra_config = 0;

  // Determine if all endpoint pairs share the same endpoint mode
  assert(data.endpoints.size() > 0);
  bool shared_endpoint_mode = SharedEndpointModes(data);

  // The first part of the endpoint mode (CEM) comes directly after the
  // partition info, if it exists. If there is no partition info, the CEM comes
  // right after the block mode. In the single-partition case, we just write out
  // the entire singular CEM, but in the multi-partition case, if all CEMs are
  // the same then their shared CEM is specified directly here, too. In both
  // cases, shared_endpoint_mode is true (in the singular case,
  // shared_endpoint_mode is trivially true).
  if (shared_endpoint_mode) {
    if (num_partitions > 1) {
      bit_sink.PutBits(0, 2);
    }
    bit_sink.PutBits(static_cast<int>(data.endpoints[0].mode), 4);
  } else {
    // Here, the CEM is not shared across all endpoint pairs, and we need to
    // figure out what to place here, and what to place in the extra config
    // bits before the weight data...

    // Non-shared config modes must all be within the same class (out of four)
    // See Section C.2.11
    int min_class = 2;  // We start with 2 here instead of three because it's
                        // the highest that can be encoded -- even if all modes
                        // are class 3.
    int max_class = 0;
    for (const auto& ep_data : data.endpoints) {
      const int ep_mode_class = static_cast<int>(ep_data.mode) >> 2;
      min_class = std::min(min_class, ep_mode_class);
      max_class = std::max(max_class, ep_mode_class);
    }

    assert(max_class >= min_class);

    if (max_class - min_class > 1) {
      return std::string("Endpoint modes are invalid");
    }

    // Construct the CEM mode -- six of its bits will fit here, but otherwise
    // the rest will go in the extra configuration bits.
    base::BitStream<uint32_t> cem_encoder;

    // First encode the base class
    assert(min_class >= 0);
    assert(min_class < 3);
    cem_encoder.PutBits(min_class + 1, 2);

    // Next, encode the class selector bits -- this is simply the offset
    // from the base class
    for (const auto& ep_data : data.endpoints) {
      const int ep_mode_class = static_cast<int>(ep_data.mode) >> 2;
      const int class_selector_bit = ep_mode_class - min_class;
      assert(class_selector_bit == 0 || class_selector_bit == 1);
      cem_encoder.PutBits(class_selector_bit, 1);
    }

    // Finally, we need to choose from each class which actual mode
    // we belong to and encode those.
    for (const auto& ep_data : data.endpoints) {
      const int ep_mode = static_cast<int>(ep_data.mode) & 3;
      assert(ep_mode < 4);
      cem_encoder.PutBits(ep_mode, 2);
    }
    assert(cem_encoder.Bits() == 2 + num_partitions * 3);

    uint32_t encoded_cem;
    cem_encoder.GetBits(2 + num_partitions * 3, &encoded_cem);

    // Since only six bits fit here before the color endpoint data, the rest
    // need to go in the extra config data.
    extra_config = encoded_cem >> 6;

    // Write out the six bits we had
    bit_sink.PutBits(encoded_cem, 6);
  }

  // If we have a dual-plane channel, we can tack that onto our extra config
  // data
  if (data.dual_plane_channel.hasValue()) {
    const int channel = data.dual_plane_channel.value();
    assert(channel < 4);
    extra_config <<= 2;
    extra_config |= channel;
  }

  // Get the range of endpoint values. It can't be -1 because we should have
  // checked for that much earlier.
  const int color_value_range = data.endpoint_range
      ? data.endpoint_range.value()
      : EndpointRangeForBlock(data);

  assert(color_value_range != kEndpointRange_ReturnInvalidWeightDims);
  if (color_value_range == kEndpointRange_ReturnNotEnoughColorBits) {
    return { "Intermediate block emits illegal color range" };
  }

  IntegerSequenceEncoder color_enc(color_value_range);
  for (const auto& ep_data : data.endpoints) {
    for (int color : ep_data.colors) {
      if (color > color_value_range) {
        return { "Color outside available color range!" };
      }

      color_enc.AddValue(color);
    }
  }
  color_enc.Encode(&bit_sink);

  // Now we need to skip some bits to get to the extra configuration bits. The
  // number of bits we need to skip depends on where we are in the stream and
  // where we need to get to.
  const int extra_config_bit_position = ExtraConfigBitPosition(data);
  const int extra_config_bits =
      128 - num_weight_bits - extra_config_bit_position;
  assert(extra_config_bits >= 0);
  assert(extra_config < 1 << extra_config_bits);

  // Make sure the color encoder didn't write more than we thought it would.
  int bits_to_skip = extra_config_bit_position - bit_sink.Bits();
  assert(bits_to_skip >= 0);

  while (bits_to_skip > 0) {
    const int skipping = std::min(32, bits_to_skip);
    bit_sink.PutBits(0, skipping);
    bits_to_skip -= skipping;
  }

  // Finally, write out the rest of the config bits.
  bit_sink.PutBits(extra_config, extra_config_bits);

  // We should be right up to the weight bits...
  assert(bit_sink.Bits() == 128 - num_weight_bits);

  // Flush out our bit writer and write out the weight bits
  base::UInt128 astc_bits;
  bit_sink.GetBits(128 - num_weight_bits, &astc_bits);

  base::UInt128 rev_weight_bits;
  weight_sink.GetBits(weight_sink.Bits(), &rev_weight_bits);

  astc_bits |= base::ReverseBits(rev_weight_bits);

  // And we're done! Whew!
  *pb = astc_bits;
  return PhysicalASTCBlock(*pb).IsIllegalEncoding();
}

base::Optional<std::string> Pack(const VoidExtentData& data,
                                 base::UInt128* pb) {
  *pb = PackVoidExtentBlock(data.r, data.g, data.b, data.a, data.coords);
  return PhysicalASTCBlock(*pb).IsIllegalEncoding();
}

}  // namespace astc_codec
