// 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 encoding.
//

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <memory>

#include "src/common/lossy/transforms.h"
#include "src/enc/analysis.h"
#include "src/enc/wp2_enc_i.h"
#include "src/utils/utils.h"
#include "src/wp2/format_constants.h"

namespace WP2 {

WP2Status SyntaxWriter::Init(ANSDictionaries* const dicts,
                             const EncoderConfig& config,
                             const GlobalParams& gparams, const YUVPlane& yuv,
                             ChromaSubsampling chroma_subsampling,
                             const Rectangle& tile_rect, uint32_t num_blocks,
                             bool use_aom_coeffs, bool use_splits,
                             const ProgressRange& alpha_progress) {
  config_ = &config;
  dicts_ = dicts;
  recorded_blocks_ = 0;
  tile_rect_ = tile_rect;
  gparams_ = &gparams;
  assert(gparams_->IsOk());
  chroma_subsampling_ = chroma_subsampling;
  use_splits_ = use_splits;

  num_blocks_ = num_blocks;
  // Number of transforms is unknown yet, use a higher bound.
  num_transforms_ = std::min(
      num_blocks * 4, SizeBlocks(yuv.GetWidth()) * SizeBlocks(yuv.GetHeight()));
  // Deal with context.
  WP2_CHECK_STATUS(context_.Init(use_aom_coeffs, gparams_->segments_.size(),
                                 gparams_->explicit_segment_ids_,
                                 tile_rect.width));

  WP2_CHECK_STATUS(residual_writer_.Init(context_.use_aom(),
                                         gparams_->maybe_use_lossy_alpha_));


  if (gparams_->has_alpha_) {
    WP2_CHECK_STATUS(alpha_writer_.Init(*config_, gparams, context_, yuv,
                                        tile_rect, alpha_progress));
  } else {
    WP2_CHECK_STATUS(alpha_progress.AdvanceBy(1.));
  }

  if (kDebugPrintRate) {
    WP2_CHECK_ALLOC_OK(residual_rate_.resize(num_blocks));
  }

  return WP2_STATUS_OK;
}

WP2Status SyntaxWriter::CopyFrom(const SyntaxWriter& other,
                                 ANSDictionaries* const dicts) {
  config_ = other.config_;

  WP2_CHECK_OK(dicts != nullptr, WP2_STATUS_NULL_PARAMETER);
  WP2_CHECK_OK(dicts != other.dicts_, WP2_STATUS_INVALID_PARAMETER);
  dicts_ = dicts;

  WP2_CHECK_STATUS(context_.CopyFrom(other.context_));
  if (other.gparams_->has_alpha_) {
    WP2_CHECK_STATUS(alpha_writer_.CopyFrom(other.alpha_writer_, context_));
  }

  num_blocks_ = other.num_blocks_;
  num_transforms_ = other.num_transforms_;
  recorded_blocks_ = other.recorded_blocks_;
  tile_rect_ = other.tile_rect_;
  chroma_subsampling_ = other.chroma_subsampling_;
  gparams_ = other.gparams_;
  use_splits_ = other.use_splits_;

  WP2_CHECK_STATUS(
      symbol_writer_.CopyFrom(other.symbol_writer_, *dicts_, *other.dicts_));
  WP2_CHECK_STATUS(symbol_recorder_.CopyFrom(other.symbol_recorder_));
  WP2_CHECK_STATUS(counters_.CopyFrom(other.counters_, symbol_recorder_));
  residual_writer_.CopyFrom(other.residual_writer_);

  WP2_CHECK_ALLOC_OK(residual_rate_.copy_from(other.residual_rate_));
  return WP2_STATUS_OK;
}

WP2Status SyntaxWriter::InitPass() {
  SymbolsInfo symbols_info;
  WP2_CHECK_STATUS(symbols_info.InitLossy(
      gparams_->segments_.size(), gparams_->partition_set_,
      gparams_->maybe_use_lossy_alpha_, context_.use_aom(), use_splits_));
  symbols_info.SetMinMax(kSymbolModeY, /*min=*/0,
                         /*max=*/gparams_->y_preds_.GetMaxMode());
  if (gparams_->maybe_use_lossy_alpha_) {
    symbols_info.SetMinMax(kSymbolModeA, /*min=*/0,
                           /*max=*/gparams_->a_preds_.GetMaxMode());
  }
  symbols_info.SetMinMax(kSymbolModeUV, /*min=*/0,
                         /*max=*/gparams_->uv_preds_.GetMaxMode());
  const uint32_t num_channels = (gparams_->maybe_use_lossy_alpha_ ? 4 : 3);
  for (Channel c : {kYChannel, kUChannel, kVChannel, kAChannel}) {
    if (c == kAChannel && !gparams_->maybe_use_lossy_alpha_) continue;
    WP2_CHECK_STATUS(symbols_info.SetMinMax(
        kSymbolDC, ResidualIO::GetCluster(c, num_channels), /*min=*/0,
        /*max=*/gparams_->GetMaxDCRange(c)));
  }
  symbols_info.SetClusters(kSymbolDC, symbols_info.NumClusters(kSymbolDC));

  WP2_CHECK_STATUS(symbol_writer_.Init(symbols_info, config_->effort));
  WP2_CHECK_STATUS(symbol_writer_.Allocate());
  if (pass_number_ == 0) {
    WP2_CHECK_STATUS(symbol_recorder_.Allocate(
        symbols_info, /*num_records=*/num_blocks_ * kMaxBlockSize2));
  } else {
    WP2_CHECK_STATUS(symbol_recorder_.MakeBackup());
  }
  ++pass_number_;
  WP2_CHECK_STATUS(
      counters_.Init(config_->effort, context_.use_aom(), symbol_recorder_));
  context_.Reset();
  if (recorded_blocks_ > 0) WP2_CHECK_STATUS(ResetRecord());
  return WP2_STATUS_OK;
}

WP2Status SyntaxWriter::WriteHeader(ANSEncBase* const enc) {
  const uint32_t max_num_blocks =
      SizeBlocks(tile_rect_.width) * SizeBlocks(tile_rect_.height);
  // The minimum number of blocks is not accurate but it is not worth it to have
  // a more complex solution (neglictible pessimization).
  const uint32_t min_num_blocks = std::max(1u, max_num_blocks / kMaxBlockSize2);
  // This is also used for partitioning with an upper bound of 'num_blocks_'.
  assert((num_blocks_ == max_num_blocks) || (recorded_blocks_ == num_blocks_));
  ANSDebugPrefix prefix(enc, "GlobalHeader");

  // TODO(skal): differential-write of gparams_

  enc->PutBool(context_.use_aom(), "use_aom_coeffs");
  if (gparams_->partition_snapping_) {
    enc->PutBool(use_splits_, "use_splits");
  } else {
    assert(!use_splits_);
  }

  // Write dictionaries.
  PutLargeRange(num_blocks_, min_num_blocks, max_num_blocks, enc, "num_blocks");

  // If there's only one block, we don't need this global value, we'll signal
  // the subsampling mode for that block later.
  if (chroma_subsampling_ != ChromaSubsampling::kSingleBlock) {
    enc->PutRValue((int)chroma_subsampling_,
                   (int)ChromaSubsampling::kSingleBlock, "chroma_subsampling");
  }

  if (gparams_->explicit_segment_ids_) {
    WP2_CHECK_STATUS(symbol_writer_.WriteHeader(kSymbolSegmentId, num_blocks_,
                                                symbol_recorder_, "segment_id",
                                                enc, dicts_));
  }

  if (gparams_->use_rnd_mtx_) {
    WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
        kSymbolRndMtx0, num_blocks_, symbol_recorder_, "rnd_mtx", enc, dicts_));
    WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
        kSymbolUseRandomMatrix, num_blocks_, symbol_recorder_, "use_rnd_mtx",
        enc, dicts_));
  }
  WP2_CHECK_STATUS(
      symbol_writer_.WriteHeader(kSymbolSplitTransform, num_blocks_,
                                 symbol_recorder_, "split_tf", enc, dicts_));
  if (chroma_subsampling_ == ChromaSubsampling::kSingleBlock ||
      chroma_subsampling_ == ChromaSubsampling::kAdaptive) {
    WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
        kSymbolYuv420, num_blocks_, symbol_recorder_, "yuv420", enc, dicts_));
  }
  WP2_CHECK_STATUS(symbol_writer_.WriteHeader(kSymbolTransform, num_blocks_,
                                              symbol_recorder_, "transform",
                                              enc, dicts_));

  WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
      kSymbolModeY, num_blocks_, symbol_recorder_, "mode", enc, dicts_));
  WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
      kSymbolModeUV, num_blocks_, symbol_recorder_, "mode", enc, dicts_));

  // TODO(maryla): not necessary if the SignalingCflPredictor isn't used.
  const uint32_t num_channels_using_cfl =
      gparams_->maybe_use_lossy_alpha_ ? 3 : 2;
  WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
      kSymbolCflSlope, num_channels_using_cfl * num_blocks_, symbol_recorder_,
      "cfl", enc, dicts_));

  WP2_CHECK_STATUS(symbol_writer_.WriteHeader(kSymbolBlockSize, num_blocks_,
                                              symbol_recorder_, "block_size",
                                              enc, dicts_));

  const uint32_t num_coeffs_max =
      max_num_blocks * kMinBlockSizePix * kMinBlockSizePix;
  const uint32_t num_coeffs_max_uv =
      (chroma_subsampling_ == ChromaSubsampling::k420) ? num_coeffs_max / 4
                                                       : num_coeffs_max;
  // We should always have a UV block.
  assert(num_coeffs_max_uv > 0);

  WP2_CHECK_STATUS(context_.segment_id_predictor().WriteHeader(enc));

  if (gparams_->has_alpha_) {
    WP2_CHECK_STATUS(alpha_writer_.WriteHeader(num_coeffs_max, enc));

    if (alpha_writer_.GetAlphaMode() == kAlphaModeLossy) {
      WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
          kSymbolBlockAlphaMode, num_blocks_, symbol_recorder_,
          "block_alpha_mode", enc, dicts_));
    }
    if (alpha_writer_.GetAlphaMode() != kAlphaModeLossless) {
      WP2_CHECK_STATUS(symbol_writer_.WriteHeader(
          kSymbolModeA, num_blocks_, symbol_recorder_, "mode", enc, dicts_));
    }
  }

  WP2_CHECK_STATUS(residual_writer_.WriteHeader(
      num_coeffs_max, num_coeffs_max_uv, num_transforms_,
      gparams_->has_alpha_ &&
          (alpha_writer_.GetAlphaMode() != kAlphaModeLossless),
      symbol_recorder_, dicts_, enc, &symbol_writer_));

  return enc->GetStatus();
}

void SyntaxWriter::WriteBlockBeforeCoeffs(const CodedBlock& cb,
                                          SymbolManager* const sm,
                                          ANSEncBase* const enc) {
  context_.segment_id_predictor().WriteId(cb, sm, enc);
  context_.segment_id_predictor().RecordId(cb);

  if (gparams_->has_alpha_) {
    alpha_writer_.WriteBlockBeforeCoeffs(cb, sm, enc);
  } else if (!gparams_->maybe_use_lossy_alpha_) {
    assert(!cb.HasLossyAlpha());
  }

  for (Channel channel : {kYChannel, kAChannel, kUChannel, kVChannel}) {
    if (channel == kAChannel && !cb.HasLossyAlpha()) continue;
    WritePredictors(cb, channel, sm, enc);
  }

  if (chroma_subsampling_ == ChromaSubsampling::kSingleBlock ||
      chroma_subsampling_ == ChromaSubsampling::kAdaptive) {
    sm->Process(kSymbolYuv420, cb.is420_, "yuv420", enc);
  }

  for (Channel channel : {kYChannel, kUChannel, kVChannel, kAChannel}) {
    if (channel == kAChannel && !cb.HasLossyAlpha()) continue;
    WriteSplitTransform(cb, channel, sm, enc);
    WriteHasCoeffs(cb, channel, sm, enc);
    WriteTransform(cb, channel, sm, enc);
  }

  if (!context_.use_aom()) {
    ANSDebugPrefix prefix(enc, "coeff_method");
    gparams_->segments_[cb.id_].StoreEncodingMethods(cb, sm, enc);
  }

  if (cb.mtx_set_ != nullptr) {
#if defined(ENABLE_RND_MTX)
    const bool can_use =
        gparams_->mtx_set_.IsOk(cb.mtx_[kYChannel], cb.tdim(kYChannel));
    if (can_use) {
      sm->Process(kSymbolUseRandomMatrix, cb.use_mtx_, "use_rnd_mtx", enc);
      if (cb.use_mtx_) {
        sm->Process(kSymbolRndMtx0, cb.mtx_[kYChannel], "rnd_mtx_y", enc);
      }
    } else {
      assert(!cb.use_mtx_);
    }
#endif
  }
}

void SyntaxWriter::WritePredictors(const CodedBlock& cb, Channel channel,
                                   SymbolManager* const sm,
                                   ANSEncBase* const enc) {
  ANSDebugPrefix prefix(enc, "pred_modes");
  const CodedBlock::CodingParams& params = cb.GetCodingParams(channel);
  if (channel == kYChannel) {
    if (cb.y_context_is_constant_) return;
    sm->Process(kSymbolModeY, params.pred->mode(), "y", enc);
  } else if (channel == kUChannel) {
    sm->Process(kSymbolModeUV, params.pred->mode(), "uv", enc);
  } else if (channel == kVChannel) {
    // kVChannel is not written as it is the same as kUChannel.
  } else {
    sm->Process(kSymbolModeA, params.pred->mode(), "a", enc);
  }
  /* sub_mode = */params.pred->WriteParams(cb, channel, sm, enc);
}

void SyntaxWriter::WriteSplitTransform(const CodedBlock& cb, Channel channel,
                                       SymbolManager* const sm,
                                       ANSEncBase* const enc) {
  if (channel == kYChannel &&
      GetSplitSize(cb.dim(), /*split=*/true) != cb.dim()) {
    sm->Process(kSymbolSplitTransform, cb.GetCodingParams(channel).split_tf,
                "split_tf", enc);
  } else {
    assert(!cb.GetCodingParams(channel).split_tf);
  }
}

void SyntaxWriter::WriteHasCoeffs(const CodedBlock& cb, Channel channel,
                                  SymbolManager* const sm,
                                  ANSEncBase* const enc) {
  for (uint32_t tf_i = 0; tf_i < cb.GetNumTransforms(channel); ++tf_i) {
    const bool tf_has_coeffs = (cb.num_coeffs_[channel][tf_i] != 0);
    const uint32_t cluster = (uint32_t)channel;
    sm->Process(kSymbolHasCoeffs, cluster, tf_has_coeffs ? 1 : 0, "has_coeffs",
                enc);
  }
}

void SyntaxWriter::WriteTransform(const CodedBlock& cb, Channel channel,
                                  SymbolManager* const sm,
                                  ANSEncBase* const enc) {
  const CodedBlock::CodingParams& params = cb.GetCodingParams(channel);
  if (channel == kUChannel || channel == kVChannel || channel == kAChannel) {
    assert(params.tf == kDctDct);
  } else if (cb.HasCoeffs(channel)) {
    // TODO(maryla): try more ways to signal the transform which might be
    //               correlated to block size.
    sm->Process(kSymbolTransform, params.tf, "transform", enc);
  } else {
    // No need to signal the transform as there is no coeff.
  }
}

void SyntaxWriter::RecordBlockHeader(const CodedBlock& cb) {
  ANSEncNoop enc;
  WriteBlockBeforeCoeffs(cb, &symbol_recorder_, &enc);
}

WP2Status SyntaxWriter::WriteBlocks(const Vector<CodedBlock>& cblocks,
                                    const Vector_u16& size_order_indices,
                                    FrontMgrDoubleOrderBase* const mgr,
                                    ANSEnc* const enc) {
  assert(cblocks.size() == num_blocks_);
  assert(cblocks.size() == size_order_indices.size());
  // Note: we could call segment_ids_.InitMap(bw, bh) again here.
  WP2_CHECK_STATUS(residual_writer_.Init(context_.use_aom(),
                                         gparams_->maybe_use_lossy_alpha_));
  context_.Reset();
  assert(size_order_indices.size() == num_blocks_);
  mgr->Clear();
  uint32_t block_idx = 0;
  for (uint16_t ind : size_order_indices) {
    {
      ANSDebugPrefix prefix(enc, "BlockHeader");
      const CodedBlock& cb = cblocks[ind];
      WriteBlockSize(*mgr, cb.dim(), &symbol_writer_, enc);
      Block block_tmp;
      WP2_CHECK_ALLOC_OK(mgr->UseSize(cb.dim(), &block_tmp));
      assert(block_tmp == cb.blk());
    }
    while (true) {
      Block block;
      if (!mgr->UseReady(&block)) break;
      const CodedBlock& cb = cblocks[block_idx];
      assert(cb.blk() == block);
      WP2_CHECK_STATUS(WriteBlock(cb, block_idx, enc));
      ++block_idx;
    }
  }

  if (kDebugPrintRate) {
    float total_estimated = 0.f;
    float total_actual = 0.f;
    float total_difference = 0.f;
    float max_difference = 0.f;
    uint32_t num_non_zero = 0;
    for (uint32_t i = 0; i < cblocks.size(); ++i) {
      const CodedBlock& cb = cblocks[i];
      for (Channel c : {kYChannel, kUChannel, kVChannel, kAChannel}) {
        if (c == kAChannel && !cb.HasLossyAlpha()) continue;

        const float estimated_rate = residual_rate_[i][c];
        const float actual_rate = residual_rate_[i][4 + c];
        total_estimated += estimated_rate;
        total_actual += actual_rate;

        if (actual_rate == 0 && estimated_rate == 0) continue;

        fprintf(stderr,
                "block (%3d %3d) channel %d rate: estimated %6.2f vs real "
                "%6.2f, %+4.2f",
                cb.x(), cb.y(), c, estimated_rate, actual_rate,
                actual_rate - estimated_rate);

        if (estimated_rate != 0) {
          ++num_non_zero;
          const float relative_difference = actual_rate / estimated_rate - 1.f;
          const float abs_difference = std::abs(relative_difference);
          total_difference += abs_difference;
          if (abs_difference > max_difference) max_difference = abs_difference;
          fprintf(stderr, "  %+.2f%%\n", relative_difference * 100.f);
        } else {
          fprintf(stderr, "\n");
        }
      }
    }
    fprintf(
        stderr,
        "Total residual rate estimated %.2f vs real %.2f, "
        "%+.2f%%, average difference (for non zero rates) %.2f%% max %.2f%%\n",
        total_estimated, total_actual,
        (total_estimated / total_actual - 1.f) * 100.f,
        total_difference / num_non_zero * 100, max_difference * 100);
  }

  return enc->GetStatus();
}

WP2Status SyntaxWriter::WriteBlocksUseSplits(const Vector<CodedBlock>& cblocks,
                                             const Vector_u32& splits,
                                             ANSEnc* const enc) {
  assert(cblocks.size() == num_blocks_);
  // Note: we could call segment_ids_.InitMap(bw, bh) again here.
  WP2_CHECK_STATUS(residual_writer_.Init(context_.use_aom(),
                                         gparams_->maybe_use_lossy_alpha_));
  context_.Reset();

  SplitIteratorDefault it;
  WP2_CHECK_STATUS(
      it.Init(gparams_->partition_set_, tile_rect_.width, tile_rect_.height));

  uint32_t block_idx = 0;
  uint32_t split_idx = 0;
  while (!it.Done()) {
    if (it.CurrentBlock().splittable) {
      ANSDebugPrefix prefix(enc, "BlockHeader");
      const uint32_t split = splits[split_idx];
      WriteBlockSplit(it, split, &symbol_writer_, enc);
      it.SplitCurrentBlock(split);
      ++split_idx;
    } else {
      const CodedBlock& cb = cblocks[block_idx];
      assert(cb.blk() == it.CurrentBlock().block);
      WP2_CHECK_STATUS(WriteBlock(cb, block_idx, enc));
      it.NextBlock();
      ++block_idx;
    }
  }
  return enc->GetStatus();
}

//------------------------------------------------------------------------------

void SyntaxWriter::FindBestEncodingMethods(CodedBlock* const cb) {
  const uint32_t num_channels = (gparams_->maybe_use_lossy_alpha_ ? 4 : 3);
  for (auto c : {kYChannel, kUChannel, kVChannel, kAChannel}) {
    if (c == kAChannel && !cb->HasLossyAlpha()) continue;
    for (uint32_t tf_i = 0; tf_i < cb->GetNumTransforms(c); ++tf_i) {
      if (context_.use_aom()) {
        ResidualWriter::SetGeometry(cb->num_coeffs_[c][tf_i],
                                    &cb->method_[c][tf_i]);
      } else {
        residual_writer_.FindBestEncodingMethod(
            cb->tdim(c), cb->coeffs_[c][tf_i], cb->num_coeffs_[c][tf_i],
            cb->IsFirstCoeffDC(c), c, num_channels, counters_.residuals(),
            &cb->method_[c][tf_i]);
      }
    }
  }
}

WP2Status SyntaxWriter::DecideAlpha(CodedBlock* const cb,
                                    const BlockModes& modes,
                                    BlockScorer* const scorer) {
  return alpha_writer_.DecideAlpha(cb, modes, residual_writer_, &counters_,
                                   scorer);
}

WP2Status SyntaxWriter::RecordAlpha(const CodedBlock& cb) {
  return alpha_writer_.Record(cb);
}

WP2Status SyntaxWriter::SetInitialSegmentIds() {
  const Rectangle padded_tile_rect = {tile_rect_.x, tile_rect_.y,
                                      Pad(tile_rect_.width, kPredWidth),
                                      Pad(tile_rect_.height, kPredWidth)};
  CodedBlock cb;
  cb.SetDimDefault(Block(0, 0, BLK_4x4));
  FrontMgr4x4 mgr;
  WP2_CHECK_STATUS(
      mgr.InitBase(padded_tile_rect.width, padded_tile_rect.height));
  for (uint32_t y = 0; y < SizeBlocks(padded_tile_rect.height); ++y) {
    for (uint32_t x = 0; x < SizeBlocks(padded_tile_rect.width); ++x) {
      cb.SetXY(mgr, x, y);
      cb.id_ = AssignSegmentId(*config_, *gparams_, padded_tile_rect, cb.blk());
      context_.segment_id_predictor().InitInitialSegmentId(cb, cb.id_);
      mgr.Use4x4();
    }
  }
  return WP2_STATUS_OK;
}

//------------------------------------------------------------------------------

void SyntaxWriter::Record(const CodedBlock& cb) {
  assert(recorded_blocks_ < num_blocks_);

  RecordBlockHeader(cb);
  const uint32_t num_channels = (gparams_->maybe_use_lossy_alpha_ ? 4 : 3);
  for (Channel channel : {kYChannel, kUChannel, kVChannel, kAChannel}) {
    if (channel == kAChannel && !cb.HasLossyAlpha()) continue;

    if (kDebugPrintRate) {
      residual_rate_[recorded_blocks_][channel] = cb.ResidualRate(
          context_, channel, num_channels, counters_.residuals());
    }

    residual_writer_.RecordCoeffs(cb, channel, &symbol_recorder_);
  }

  ++recorded_blocks_;
}

void SyntaxWriter::RecordSize(const FrontMgrDoubleOrderBase& mgr,
                              BlockSize dim) {
  RecordSize(dim, mgr.GetMaxPossibleBlock().dim(), mgr.GetPartitionSet());
}

void SyntaxWriter::RecordSize(BlockSize dim, BlockSize max_possible_size,
                              PartitionSet partition_set) {
  assert(!use_splits_);
  ANSEncNoop enc;
  WriteBlockSize(dim, max_possible_size, partition_set, &symbol_recorder_,
                 &enc);
}

WP2Status SyntaxWriter::RecordSplit(const SplitIteratorBase& mgr,
                                    uint32_t split_idx) {
  assert(use_splits_);
  ANSEncNoop enc;
  WriteBlockSplit(mgr, split_idx, &symbol_recorder_, &enc);
  return WP2_STATUS_OK;
}

WP2Status SyntaxWriter::ResetRecord() {
  recorded_blocks_ = 0;
  WP2_CHECK_STATUS(symbol_recorder_.ResetRecord(/*reset_backup=*/false));
  if (gparams_->has_alpha_) {
    WP2_CHECK_STATUS(alpha_writer_.ResetRecord());
  }
  return WP2_STATUS_OK;
}

WP2Status SyntaxWriter::WriteBlock(const CodedBlock& cb, uint32_t block_index,
                                   ANSEnc* const enc) {
  {
    ANSDebugPrefix prefix(enc, "BlockHeader");
    WriteBlockBeforeCoeffs(cb, &symbol_writer_, enc);
  }

  float previous_cost;
  if (kDebugPrintRate) {
    previous_cost = enc->GetCost();
  }

  for (Channel c : {kYChannel, kUChannel, kVChannel, kAChannel}) {
    if (c == kAChannel && !cb.HasLossyAlpha()) continue;

    residual_writer_.WriteCoeffs(cb, c, enc, &symbol_writer_);
    if (kDebugPrintRate) {
      const float cost = enc->GetCost();
      const float actual_rate = cost - previous_cost;
      residual_rate_[block_index][4 + c] = actual_rate;
      previous_cost = cost;
    }
  }

  if (gparams_->has_alpha_) {
    WP2_CHECK_STATUS(alpha_writer_.Write(cb, enc));
  }
  if (cb.HasLossyAlpha()) assert(gparams_->has_alpha_);

#if defined(WP2_ENC_DEC_DEEP_MATCH)
  PutRawPixels(cb, cb.out_, enc);  // Debug
#endif
  return WP2_STATUS_OK;
}

}  // namespace WP2
