// Copyright 2023 Google LLC
// SPDX-License-Identifier: BSD-2-Clause
// Encode a fuzzed image split into a grid and decode it incrementally.
// Compare the output with a non-incremental decode.

#include <cassert>
#include <cstdint>
#include <vector>

#include "avif/internal.h"
#include "avif_fuzztest_helpers.h"
#include "avifincrtest_helpers.h"
#include "aviftest_helpers.h"
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

using ::fuzztest::Arbitrary;
using ::fuzztest::InRange;

namespace avif {
namespace testutil {
namespace {

::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();

// Encodes an image into an AVIF grid then decodes it.
void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder,
                           DecoderPtr decoder, uint32_t grid_cols,
                           uint32_t grid_rows, bool is_encoded_data_persistent,
                           bool give_size_hint_to_decoder) {
  ASSERT_NE(image, nullptr);
  ASSERT_NE(encoder, nullptr);

  const std::vector<ImagePtr> cells =
      ImageToGrid(image.get(), grid_cols, grid_rows);
  if (cells.empty()) return;
  const uint32_t cell_width = cells.front()->width;
  const uint32_t cell_height = cells.front()->height;
  const uint32_t encoded_width = std::min(image->width, grid_cols * cell_width);
  const uint32_t encoded_height =
      std::min(image->height, grid_rows * cell_height);

  const avifImage* gain_map =
      image->gainMap != nullptr ? image->gainMap->image : nullptr;
  if (gain_map != nullptr) {
    std::vector<ImagePtr> gain_map_cells =
        ImageToGrid(gain_map, grid_cols, grid_rows);
    if (gain_map_cells.empty()) return;
    ASSERT_EQ(gain_map_cells.size(), cells.size());
    for (size_t i = 0; i < gain_map_cells.size(); ++i) {
      cells[i]->gainMap = avifGainMapCreate();
      cells[i]->gainMap->image = gain_map_cells[i].release();
    }
  }

  AvifRwData encoded_data;
  const avifResult encoder_result = avifEncoderAddImageGrid(
      encoder.get(), grid_cols, grid_rows, UniquePtrToRawPtr(cells).data(),
      AVIF_ADD_IMAGE_FLAG_SINGLE);
  if (((grid_cols > 1 || grid_rows > 1) &&
       !avifAreGridDimensionsValid(image->yuvFormat, encoded_width,
                                   encoded_height, cell_width, cell_height,
                                   nullptr))) {
    ASSERT_TRUE(encoder_result == AVIF_RESULT_INVALID_IMAGE_GRID)
        << avifResultToString(encoder_result);
    return;
  }
  if ((gain_map != nullptr) &&
      ((grid_cols > 1 || grid_rows > 1) &&
       !avifAreGridDimensionsValid(
           gain_map->yuvFormat,
           std::min(gain_map->width,
                    grid_cols * cells.front()->gainMap->image->width),
           std::min(gain_map->height,
                    grid_rows * cells.front()->gainMap->image->height),
           cells.front()->gainMap->image->width,
           cells.front()->gainMap->image->height, nullptr))) {
    ASSERT_TRUE(encoder_result == AVIF_RESULT_INVALID_IMAGE_GRID)
        << avifResultToString(encoder_result);
    return;
  }

  ASSERT_EQ(encoder_result, AVIF_RESULT_OK)
      << avifResultToString(encoder_result);

  const avifResult finish_result =
      avifEncoderFinish(encoder.get(), &encoded_data);
  ASSERT_EQ(finish_result, AVIF_RESULT_OK) << avifResultToString(finish_result);

  const bool expect_whole_file_read = decoder->enableDecodingGainMap &&
                                      decoder->enableParsingGainMapMetadata &&
                                      !decoder->ignoreColorAndAlpha;
  const avifResult decode_result = DecodeNonIncrementallyAndIncrementally(
      encoded_data, decoder.get(), is_encoded_data_persistent,
      give_size_hint_to_decoder, /*use_nth_image_api=*/true, cell_height,
      /*enable_fine_incremental_check=*/false, expect_whole_file_read);
  ASSERT_EQ(decode_result, AVIF_RESULT_OK) << avifResultToString(decode_result);
}

// Note that avifGainMapMetadata is passed as a byte array
// because the C array fields in the struct seem to prevent fuzztest from
// handling it natively.
ImagePtr AddGainMapToImage(
    ImagePtr image, ImagePtr gain_map,
    const std::array<uint8_t, sizeof(avifGainMapMetadata)>& metadata) {
  image->gainMap = avifGainMapCreate();
  image->gainMap->image = gain_map.release();
  std::memcpy(&image->gainMap->metadata, metadata.data(), metadata.size());
  return image;
}

inline auto ArbitraryAvifImageWithGainMap() {
  return fuzztest::Map(
      AddGainMapToImage, ArbitraryAvifImage(), ArbitraryAvifImage(),
      fuzztest::Arbitrary<std::array<uint8_t, sizeof(avifGainMapMetadata)>>());
}

FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeGridValid)
    .WithDomains(fuzztest::OneOf(ArbitraryAvifImage(),
                                 ArbitraryAvifImageWithGainMap()),
                 ArbitraryAvifEncoder(), ArbitraryAvifDecoder(),
                 /*grid_cols=*/InRange<uint32_t>(1, 32),
                 /*grid_rows=*/InRange<uint32_t>(1, 32),
                 /*is_encoded_data_persistent=*/Arbitrary<bool>(),
                 /*give_size_hint_to_decoder=*/Arbitrary<bool>());

}  // namespace
}  // namespace testutil
}  // namespace avif
