// Copyright 2022 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#include <fstream>
#include <iostream>
#include <string>
#include <tuple>

#include "avif/avif.h"
#include "avifincrtest_helpers.h"
#include "aviftest_helpers.h"
#include "gtest/gtest.h"

using testing::Bool;
using testing::Combine;
using testing::Values;

namespace libavif {
namespace {

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

// Used to pass the data folder path to the GoogleTest suites.
const char* data_path = nullptr;

// Reads the file with file_name into bytes and returns them.
testutil::AvifRwData ReadFile(const char* file_name) {
  std::ifstream file(std::string(data_path) + "/" + file_name,
                     std::ios::binary | std::ios::ate);
  testutil::AvifRwData bytes;
  if (avifRWDataRealloc(&bytes, file.good() ? static_cast<size_t>(file.tellg())
                                            : 0) != AVIF_RESULT_OK) {
    return {};
  }
  file.seekg(0, std::ios::beg);
  file.read(reinterpret_cast<char*>(bytes.data),
            static_cast<std::streamsize>(bytes.size));
  return bytes;
}

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

// Check that non-incremental and incremental decodings of a grid AVIF produce
// the same pixels.
TEST(IncrementalTest, Decode) {
  const testutil::AvifRwData encoded_avif = ReadFile("sofa_grid1x5_420.avif");
  ASSERT_NE(encoded_avif.size, 0u);
  testutil::AvifImagePtr reference(avifImageCreateEmpty(), avifImageDestroy);
  ASSERT_NE(reference, nullptr);
  testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
  ASSERT_NE(decoder, nullptr);
  ASSERT_EQ(avifDecoderReadMemory(decoder.get(), reference.get(),
                                  encoded_avif.data, encoded_avif.size),
            AVIF_RESULT_OK);

  // Cell height is hardcoded because there is no API to extract it from an
  // encoded payload.
  testutil::DecodeIncrementally(
      encoded_avif, /*is_persistent=*/true, /*give_size_hint=*/true,
      /*use_nth_image_api=*/false, *reference, /*cell_height=*/154,
      /*enable_fine_incremental_check=*/true);
}

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

class IncrementalTest
    : public testing::TestWithParam<std::tuple<
          /*width=*/uint32_t, /*height=*/uint32_t, /*create_alpha=*/bool,
          /*flat_cells=*/bool, /*encoded_avif_is_persistent=*/bool,
          /*give_size_hint=*/bool, /*use_nth_image_api=*/bool>> {};

// Encodes then decodes a window of width*height pixels at the middle of the
// image. Check that non-incremental and incremental decodings produce the same
// pixels.
TEST_P(IncrementalTest, EncodeDecode) {
  const uint32_t width = std::get<0>(GetParam());
  const uint32_t height = std::get<1>(GetParam());
  const bool create_alpha = std::get<2>(GetParam());
  const bool flat_cells = std::get<3>(GetParam());
  const bool encoded_avif_is_persistent = std::get<4>(GetParam());
  const bool give_size_hint = std::get<5>(GetParam());
  const bool use_nth_image_api = std::get<6>(GetParam());

  // Load an image. It does not matter that it comes from an AVIF file.
  testutil::AvifImagePtr image(avifImageCreateEmpty(), avifImageDestroy);
  ASSERT_NE(image, nullptr);
  const testutil::AvifRwData image_bytes = ReadFile("sofa_grid1x5_420.avif");
  ASSERT_NE(image_bytes.size, 0u);
  testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
  ASSERT_NE(decoder, nullptr);
  ASSERT_EQ(avifDecoderReadMemory(decoder.get(), image.get(), image_bytes.data,
                                  image_bytes.size),
            AVIF_RESULT_OK);

  // Encode then decode it.
  testutil::AvifRwData encoded_avif;
  uint32_t cell_width, cell_height;
  testutil::EncodeRectAsIncremental(*image, width, height, create_alpha,
                                    flat_cells, &encoded_avif, &cell_width,
                                    &cell_height);
  testutil::DecodeNonIncrementallyAndIncrementally(
      encoded_avif, encoded_avif_is_persistent, give_size_hint,
      use_nth_image_api, cell_height, /*enable_fine_incremental_check=*/true);
}

INSTANTIATE_TEST_SUITE_P(WholeImage, IncrementalTest,
                         Combine(/*width=*/Values(1024),
                                 /*height=*/Values(770),
                                 /*create_alpha=*/Values(true),
                                 /*flat_cells=*/Bool(),
                                 /*encoded_avif_is_persistent=*/Values(true),
                                 /*give_size_hint=*/Values(true),
                                 /*use_nth_image_api=*/Values(false)));

// avifEncoderAddImageInternal() only accepts grids of one unique cell, or grids
// where width and height are both at least 64.
INSTANTIATE_TEST_SUITE_P(SingleCell, IncrementalTest,
                         Combine(/*width=*/Values(1),
                                 /*height=*/Values(1),
                                 /*create_alpha=*/Bool(),
                                 /*flat_cells=*/Bool(),
                                 /*encoded_avif_is_persistent=*/Bool(),
                                 /*give_size_hint=*/Bool(),
                                 /*use_nth_image_api=*/Bool()));

// Chroma subsampling requires even dimensions. See ISO 23000-22
// section 7.3.11.4.2.
INSTANTIATE_TEST_SUITE_P(SinglePixel, IncrementalTest,
                         Combine(/*width=*/Values(64, 66),
                                 /*height=*/Values(64, 66),
                                 /*create_alpha=*/Bool(),
                                 /*flat_cells=*/Bool(),
                                 /*encoded_avif_is_persistent=*/Bool(),
                                 /*give_size_hint=*/Bool(),
                                 /*use_nth_image_api=*/Bool()));

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

}  // namespace
}  // namespace libavif

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  if (argc < 2) {
    std::cerr
        << "The path to the test data folder must be provided as an argument"
        << std::endl;
    return 1;
  }
  libavif::data_path = argv[1];
  return RUN_ALL_TESTS();
}
