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

#include <array>
#include <iostream>
#include <ostream>

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

namespace libavif {
namespace {

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

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

bool GetIoStatsFromEncode(avifIOStats& encoder_io_stats, int quality,
                          int qualityAlpha, bool translucent,
                          int num_frames = 1, bool encode_as_grid = false) {
  testutil::AvifImagePtr image =
      testutil::ReadImage(data_path, "paris_exif_xmp_icc.jpg");
  AVIF_CHECK(image != nullptr);
  if (translucent) {
    // Make up some alpha from luma.
    image->alphaPlane = image->yuvPlanes[AVIF_CHAN_Y];
    image->alphaRowBytes = image->yuvRowBytes[AVIF_CHAN_Y];
    AVIF_CHECK(!image->imageOwnsAlphaPlane);
  }

  testutil::AvifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
  AVIF_CHECK(encoder != nullptr);
  encoder->speed = AVIF_SPEED_FASTEST;
  encoder->quality = quality;
  encoder->qualityAlpha = qualityAlpha;
  for (int frame = 0; frame < num_frames; ++frame) {
    if (encode_as_grid) {
      const avifCropRect left_rect = {0, 0, image->width / 2, image->height};
      testutil::AvifImagePtr left_cell(avifImageCreateEmpty(),
                                       avifImageDestroy);
      AVIF_CHECK(avifImageSetViewRect(left_cell.get(), image.get(),
                                      &left_rect) == AVIF_RESULT_OK);
      const avifCropRect right_rect = {image->width / 2, 0, image->width / 2,
                                       image->height};
      testutil::AvifImagePtr right_cell(avifImageCreateEmpty(),
                                        avifImageDestroy);
      AVIF_CHECK(avifImageSetViewRect(right_cell.get(), image.get(),
                                      &right_rect) == AVIF_RESULT_OK);
      const std::array<avifImage*, 2> pointers = {left_cell.get(),
                                                  right_cell.get()};
      AVIF_CHECK(avifEncoderAddImageGrid(encoder.get(), /*gridCols=*/2,
                                         /*gridRows=*/1, pointers.data(),
                                         AVIF_ADD_IMAGE_FLAG_NONE) ==
                 AVIF_RESULT_OK);
    } else {
      AVIF_CHECK(avifEncoderAddImage(encoder.get(), image.get(),
                                     /*durationInTimescales=*/1,
                                     AVIF_ADD_IMAGE_FLAG_NONE) ==
                 AVIF_RESULT_OK);
    }

    // Watermark each frame.
    image->yuvPlanes[AVIF_CHAN_Y][0] =
        (image->yuvPlanes[AVIF_CHAN_Y][0] + 1u) % 256u;
  }

  testutil::AvifRwData encoded;
  AVIF_CHECK(avifEncoderFinish(encoder.get(), &encoded) == AVIF_RESULT_OK);
  encoder_io_stats = encoder->ioStats;

  // Make sure decoding gives the same stats.
  testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
  AVIF_CHECK(decoder != nullptr);
  AVIF_CHECK(avifDecoderSetIOMemory(decoder.get(), encoded.data,
                                    encoded.size) == AVIF_RESULT_OK);
  AVIF_CHECK(avifDecoderParse(decoder.get()) == AVIF_RESULT_OK);
  EXPECT_EQ(decoder->ioStats.colorOBUSize, encoder_io_stats.colorOBUSize);
  EXPECT_EQ(decoder->ioStats.alphaOBUSize, encoder_io_stats.alphaOBUSize);
  return true;
}

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

TEST(IoStatsTest, ColorObuSize) {
  avifIOStats io_stats;
  ASSERT_TRUE(GetIoStatsFromEncode(io_stats, AVIF_QUALITY_DEFAULT,
                                   AVIF_QUALITY_DEFAULT,
                                   /*translucent=*/false));
  EXPECT_GT(io_stats.colorOBUSize, 0u);
  EXPECT_EQ(io_stats.alphaOBUSize, 0u);
}

TEST(IoStatsTest, AlphaObuSize) {
  avifIOStats io_stats;
  ASSERT_TRUE(GetIoStatsFromEncode(io_stats, AVIF_QUALITY_WORST,
                                   AVIF_QUALITY_WORST, /*translucent=*/true));
  EXPECT_GT(io_stats.colorOBUSize, 0u);
  EXPECT_GT(io_stats.alphaOBUSize, 0u);
}

// Disabled because segfault happens with some libaom versions (such as 3.5.0)
// but not others (such as 3.6.0). TODO(yguyon): Find the commit that fixed it.
TEST(DISABLED_IoStatsTest, AnimationObuSize) {
  avifIOStats io_stats;
  ASSERT_TRUE(GetIoStatsFromEncode(io_stats, AVIF_QUALITY_LOSSLESS,
                                   AVIF_QUALITY_LOSSLESS,
                                   /*translucent=*/true));

  avifIOStats io_stats_grid;
  ASSERT_TRUE(GetIoStatsFromEncode(io_stats_grid, AVIF_QUALITY_LOSSLESS,
                                   AVIF_QUALITY_LOSSLESS, /*translucent=*/true,
                                   /*num_frames=*/3));
  EXPECT_GT(io_stats_grid.colorOBUSize, io_stats.colorOBUSize);
  EXPECT_GT(io_stats_grid.alphaOBUSize, io_stats.alphaOBUSize);
}

TEST(IoStatsTest, GridObuSize) {
  avifIOStats io_stats;
  ASSERT_TRUE(GetIoStatsFromEncode(io_stats, AVIF_QUALITY_BEST,
                                   AVIF_QUALITY_BEST, /*translucent=*/true));

  avifIOStats io_stats_grid;
  ASSERT_TRUE(GetIoStatsFromEncode(io_stats_grid, AVIF_QUALITY_BEST,
                                   AVIF_QUALITY_BEST, /*translucent=*/true,
                                   /*num_frames=*/1, /*encode_as_grid=*/true));
  EXPECT_GT(io_stats_grid.colorOBUSize, io_stats.colorOBUSize / 2);
  EXPECT_LT(io_stats_grid.colorOBUSize, io_stats.colorOBUSize * 3 / 2);
  EXPECT_GT(io_stats_grid.alphaOBUSize, io_stats.alphaOBUSize / 2);
  EXPECT_LT(io_stats_grid.alphaOBUSize, io_stats.alphaOBUSize * 3 / 2);
}

TEST(IoStatsTest, GridAnimation) {
  avifIOStats io_stats;
  // Animated grids are not allowed.
  ASSERT_FALSE(GetIoStatsFromEncode(io_stats, AVIF_QUALITY_BEST,
                                    AVIF_QUALITY_BEST, /*translucent=*/false,
                                    /*num_frames=*/3, /*encode_as_grid=*/true));
}

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

}  // namespace
}  // namespace libavif

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