// Copyright 2022 Google LLC. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause

#include "avif/avif.h"

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

#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 * dataPath = nullptr;

// Reads the file with fileName into bytes and returns them.
testutil::avifRWDataCleaner readFile(const char * fileName)
{
    std::ifstream file(std::string(dataPath) + fileName, std::ios::binary | std::ios::ate);
    testutil::avifRWDataCleaner bytes;
    avifRWDataRealloc(&bytes, file.good() ? static_cast<size_t>(file.tellg()) : 0);
    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::avifRWDataCleaner encodedAvif = readFile("sofa_grid1x5_420.avif");
    ASSERT_NE(encodedAvif.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(), encodedAvif.data, encodedAvif.size), AVIF_RESULT_OK);

    // Cell height is hardcoded because there is no API to extract it from an encoded payload.
    testutil::decodeIncrementally(encodedAvif, /*isPersistent=*/true, /*giveSizeHint=*/true, /*useNthImageApi=*/false, *reference, /*cellHeight=*/154);
}

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

class IncrementalTest : public testing::TestWithParam<std::tuple</*width=*/uint32_t,
                                                                 /*height=*/uint32_t,
                                                                 /*createAlpha=*/bool,
                                                                 /*flatCells=*/bool,
                                                                 /*encodedAvifIsPersistent=*/bool,
                                                                 /*giveSizeHint=*/bool,
                                                                 /*useNthImageApi=*/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 createAlpha = std::get<2>(GetParam());
    const bool flatCells = std::get<3>(GetParam());
    const bool encodedAvifIsPersistent = std::get<4>(GetParam());
    const bool giveSizeHint = std::get<5>(GetParam());
    const bool useNthImageApi = 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::avifRWDataCleaner imageBytes = readFile("sofa_grid1x5_420.avif");
    ASSERT_NE(imageBytes.size, 0u);
    testutil::avifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
    ASSERT_NE(decoder, nullptr);
    ASSERT_EQ(avifDecoderReadMemory(decoder.get(), image.get(), imageBytes.data, imageBytes.size), AVIF_RESULT_OK);

    // Encode then decode it.
    testutil::avifRWDataCleaner encodedAvif;
    uint32_t cellWidth, cellHeight;
    testutil::encodeRectAsIncremental(*image, width, height, createAlpha, flatCells, &encodedAvif, &cellWidth, &cellHeight);
    testutil::decodeNonIncrementallyAndIncrementally(encodedAvif, encodedAvifIsPersistent, giveSizeHint, useNthImageApi, cellHeight);
}

INSTANTIATE_TEST_SUITE_P(WholeImage,
                         IncrementalTest,
                         Combine(/*width=*/Values(1024),
                                 /*height=*/Values(770),
                                 /*createAlpha=*/Values(true),
                                 /*flatCells=*/Bool(),
                                 /*encodedAvifIsPersistent=*/Values(true),
                                 /*giveSizeHint=*/Values(true),
                                 /*useNthImageApi=*/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),
                                 /*createAlpha=*/Bool(),
                                 /*flatCells=*/Bool(),
                                 /*encodedAvifIsPersistent=*/Bool(),
                                 /*giveSizeHint=*/Bool(),
                                 /*useNthImageApi=*/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),
                                 /*createAlpha=*/Bool(),
                                 /*flatCells=*/Bool(),
                                 /*encodedAvifIsPersistent=*/Bool(),
                                 /*giveSizeHint=*/Bool(),
                                 /*useNthImageApi=*/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::dataPath = argv[1];
    return RUN_ALL_TESTS();
}
