// Copyright 2019 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.
// -----------------------------------------------------------------------------
//
// WP2 lossy decoding of the alpha plane.
//
// Author: Maryla (maryla@google.com)

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>

#include "src/common/global_params.h"
#include "src/common/lossy/block.h"
#include "src/common/symbols.h"
#include "src/dec/symbols_dec.h"
#include "src/dec/tile_dec.h"
#include "src/dec/wp2_dec_i.h"
#include "src/utils/ans.h"
#include "src/utils/ans_utils.h"
#include "src/utils/plane.h"
#include "src/utils/utils.h"
#include "src/wp2/base.h"
#include "src/wp2/decode.h"
#include "src/wp2/format_constants.h"

namespace WP2 {

AlphaReader::AlphaReader(ANSDec* const dec, const Tile& tile)
    : dec_(dec), lossless_decoder_() {
  alpha_tile_.chunk_size_is_known = tile.chunk_size_is_known;
  alpha_tile_.chunk_size = tile.chunk_size;
  alpha_tile_.input = tile.input;
  alpha_tile_.rect = tile.rect;
  alpha_tile_.num_decoded_rows = 0;
  // Alpha values cannot be premultiplied by themselves.
  WP2_ASSERT_STATUS(alpha_tile_.rgb_output.SetFormat(WP2_ARGB_32));
}

WP2Status AlphaReader::Allocate() {
  return alpha_tile_.rgb_output.Resize(alpha_tile_.rect.width,
                                       alpha_tile_.rect.height);
}

WP2Status AlphaReader::ReadHeader(const GlobalParams& gparams) {
  gparams_ = &gparams;
  ANSDebugPrefix prefix(dec_, "Alpha");
  alpha_mode_ = gparams_->maybe_use_lossy_alpha_
                    ? (AlphaMode)dec_->ReadRValue(kAlphaModeNum, "alpha_mode")
                    : kAlphaModeLossless;
  if (alpha_mode_ == kAlphaModeLossy) {
    WP2_CHECK_STATUS(
        mode_predictor_.Init(alpha_tile_.rect.width, alpha_tile_.rect.height));
  }
  return WP2_STATUS_OK;
}

void AlphaReader::GetBlockHeader(SymbolReader* const sr,
                                 CodedBlockBase* const cb) {
  if (alpha_mode_ == kAlphaModeLossy) {
    cb->alpha_mode_ = (BlockAlphaMode)mode_predictor_.Read(*cb, sr);
  } else {
    cb->alpha_mode_ = kBlockAlphaLossless;
  }
}

WP2Status AlphaReader::GetBlock(CodedBlockBase* const cb) {
  ANSDebugPrefix prefix(dec_, "Alpha");
  if (alpha_mode_ == kAlphaModeLossless) {
    WP2_CHECK_STATUS(ReadLossless(cb));
  }
  return WP2_STATUS_OK;
}

void AlphaReader::Reconstruct(CodedBlockBase* const cb) const {
  switch (cb->alpha_mode_) {
    case kBlockAlphaLossless:
      ReconstructLossless(*cb, &cb->out_.A);
      break;
    case kBlockAlphaLossy:
      cb->Reconstruct(kAChannel, /*tf_i=*/0);
      break;
    case kBlockAlphaFullTransp:
      cb->out_.A.Fill(0);
      break;
    case kBlockAlphaFullOpaque:
      cb->out_.A.Fill(kAlphaMax);
      break;
  }
}

void AlphaReader::ReconstructLossless(const CodedBlockBase& cb,
                                      Plane16* const plane) const {
  // Copy from buffer to plane, possibly replicating the right/bottom samples.
  const uint32_t block_width = cb.w_pix();
  const uint32_t block_height = cb.h_pix();
  const uint32_t max_x =
      std::min(block_width, alpha_tile_.rect.width - cb.x_pix());
  const uint32_t max_y =
      std::min(block_height, alpha_tile_.rect.height - cb.y_pix());
  assert(max_x > 0 && max_y > 0);
  for (uint32_t y = 0; y < max_y; ++y) {
    const uint8_t* const alpha_row =
        alpha_tile_.rgb_output.GetRow8(cb.y_pix() + y) + 4 * cb.x_pix() + 1;
    for (uint32_t x = 0; x < max_x; ++x) plane->At(x, y) = alpha_row[4 * x];
    // replicate right samples
    for (uint32_t x = max_x; x < block_width; ++x) {
      plane->At(x, y) = alpha_row[4 * (max_x - 1)];
    }
  }
  // replicate bottom samples
  for (uint32_t y = max_y; y < block_height; ++y) {
    memcpy(plane->Row(y), plane->Row(max_y - 1), block_width * sizeof(int16_t));
  }
}

WP2Status AlphaReader::ReadLossless(CodedBlockBase* const cb) {
  const uint32_t max_line =
      std::min(cb->y_pix() + cb->h_pix(), alpha_tile_.rect.height);

  if (next_line_ < max_line) {
    // Read as many new lines as we need for this block.
    const uint32_t lines_to_read = max_line - next_line_;
    const uint32_t num_used_bytes_before = dec_->GetNumUsedBytes();

    if (next_line_ == 0) {
      // Initialize the lossless decoder and read the header.
      lossless_decoder_.Init(DecoderConfig(), *gparams_,
                             /*image_is_premultiplied=*/false, dec_,
                             &alpha_tile_);
      WP2_CHECK_STATUS(lossless_decoder_.DecodeHeader());
    }

    WP2_CHECK_STATUS(lossless_decoder_.DecodeLines(lines_to_read));

    const uint32_t min_num_used_bytes = ANSDec::GetMinNumUsedBytesDiff(
        num_used_bytes_before, dec_->GetNumUsedBytes());
    cb->alpha_lossless_bytes_ = min_num_used_bytes;

    next_line_ = max_line;
    assert(next_line_ > 0);  // so that we won't init the decoder again
  } else {
    cb->alpha_lossless_bytes_ = 0;
  }

  return WP2_STATUS_OK;
}

}  // namespace WP2
