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

#include "avif/avif.h"

#include <algorithm>
#include <vector>

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

namespace libavif
{
namespace testutil
{
namespace
{

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

// Verifies that the first (top) rowCount rows of image1 and image2 are identical.
void comparePartialYUVA(const avifImage & image1, const avifImage & image2, uint32_t rowCount)
{
    if (rowCount == 0) {
        return;
    }
    ASSERT_EQ(image1.width, image2.width);
    ASSERT_GE(image1.height, rowCount);
    ASSERT_GE(image2.height, rowCount);
    ASSERT_EQ(image1.depth, image2.depth);
    ASSERT_EQ(image1.yuvFormat, image2.yuvFormat);
    ASSERT_EQ(image1.yuvRange, image2.yuvRange);

    avifPixelFormatInfo info;
    avifGetPixelFormatInfo(image1.yuvFormat, &info);
    const uint32_t uvWidth = (image1.width + info.chromaShiftX) >> info.chromaShiftX;
    const uint32_t uvHeight = (rowCount + info.chromaShiftY) >> info.chromaShiftY;
    const uint32_t pixelByteCount = (image1.depth > 8) ? sizeof(uint16_t) : sizeof(uint8_t);

    for (uint32_t plane = 0; plane < (info.monochrome ? 1 : AVIF_PLANE_COUNT_YUV); ++plane) {
        const uint32_t width = (plane == AVIF_CHAN_Y) ? image1.width : uvWidth;
        const uint32_t widthByteCount = width * pixelByteCount;
        const uint32_t height = (plane == AVIF_CHAN_Y) ? rowCount : uvHeight;
        const uint8_t * data1 = image1.yuvPlanes[plane];
        const uint8_t * data2 = image2.yuvPlanes[plane];
        for (uint32_t y = 0; y < height; ++y) {
            ASSERT_TRUE(std::equal(data1, data1 + widthByteCount, data2));
            data1 += image1.yuvRowBytes[plane];
            data2 += image2.yuvRowBytes[plane];
        }
    }

    if (image1.alphaPlane) {
        ASSERT_NE(image2.alphaPlane, nullptr);
        ASSERT_EQ(image1.alphaPremultiplied, image2.alphaPremultiplied);
        const uint32_t widthByteCount = image1.width * pixelByteCount;
        const uint8_t * data1 = image1.alphaPlane;
        const uint8_t * data2 = image2.alphaPlane;
        for (uint32_t y = 0; y < rowCount; ++y) {
            ASSERT_TRUE(std::equal(data1, data1 + widthByteCount, data2));
            data1 += image1.alphaRowBytes;
            data2 += image2.alphaRowBytes;
        }
    }
}

// Returns the expected number of decoded rows when availableByteCount out of byteCount were
// given to the decoder, for an image of height rows, split into cells of cellHeight rows.
uint32_t getMinDecodedRowCount(uint32_t height, uint32_t cellHeight, bool hasAlpha, size_t availableByteCount, size_t byteCount)
{
    // The whole image should be available when the full input is.
    if (availableByteCount >= byteCount) {
        return height;
    }
    // All but one cell should be decoded if at most 10 bytes are missing.
    if ((availableByteCount + 10) >= byteCount) {
        return height - cellHeight;
    }

    // Subtract the header because decoding it does not output any pixel.
    // Most AVIF headers are below 500 bytes.
    if (availableByteCount <= 500) {
        return 0;
    }
    availableByteCount -= 500;
    byteCount -= 500;
    // Alpha, if any, is assumed to be located before the other planes and to
    // represent at most 50% of the payload.
    if (hasAlpha) {
        if (availableByteCount <= (byteCount / 2)) {
            return 0;
        }
        availableByteCount -= byteCount / 2;
        byteCount -= byteCount / 2;
    }
    // Linearly map the input availability ratio to the decoded row ratio.
    const uint32_t minDecodedCellRowCount = (height / cellHeight) * availableByteCount / byteCount;
    const uint32_t minDecodedPxRowCount = minDecodedCellRowCount * cellHeight;
    // One cell is the incremental decoding granularity.
    // It is unlikely that bytes are evenly distributed among cells. Offset two of them.
    if (minDecodedPxRowCount <= (2 * cellHeight)) {
        return 0;
    }
    return minDecodedPxRowCount - 2 * cellHeight;
}

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

struct avifROPartialData
{
    avifROData available;
    size_t fullSize;
};

// Implementation of avifIOReadFunc simulating a stream from an array. See avifIOReadFunc documentation.
// io->data is expected to point to avifROPartialData.
avifResult avifIOPartialRead(struct avifIO * io, uint32_t readFlags, uint64_t offset, size_t size, avifROData * out)
{
    const avifROPartialData * data = (avifROPartialData *)io->data;
    if ((readFlags != 0) || !data || (data->fullSize < offset)) {
        return AVIF_RESULT_IO_ERROR;
    }
    if (data->fullSize < (offset + size)) {
        size = data->fullSize - offset;
    }
    if (data->available.size < (offset + size)) {
        return AVIF_RESULT_WAITING_ON_IO;
    }
    out->data = data->available.data + offset;
    out->size = size;
    return AVIF_RESULT_OK;
}

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

// Encodes the image as a grid of at most gridCols*gridRows cells.
// The cell count is reduced to fit libavif or AVIF format constraints. If impossible, the encoded output is returned empty.
// The final cellWidth and cellHeight are output.
void encodeAsGrid(const avifImage & image, uint32_t gridCols, uint32_t gridRows, avifRWData * output, uint32_t * cellWidth, uint32_t * cellHeight)
{
    // Chroma subsampling requires even dimensions. See ISO 23000-22 - 7.3.11.4.2
    const bool needEvenWidths = ((image.yuvFormat == AVIF_PIXEL_FORMAT_YUV420) || (image.yuvFormat == AVIF_PIXEL_FORMAT_YUV422));
    const bool needEvenHeights = (image.yuvFormat == AVIF_PIXEL_FORMAT_YUV420);

    ASSERT_GT(gridCols * gridRows, 0u);
    *cellWidth = image.width / gridCols;
    *cellHeight = image.height / gridRows;

    // avifEncoderAddImageGrid() only accepts grids that evenly split the image into cells at least 64 pixels wide and tall.
    while ((gridCols > 1) &&
           (((*cellWidth * gridCols) != image.width) || (*cellWidth < 64) || (needEvenWidths && ((*cellWidth & 1) != 0)))) {
        --gridCols;
        *cellWidth = image.width / gridCols;
    }
    while ((gridRows > 1) &&
           (((*cellHeight * gridRows) != image.height) || (*cellHeight < 64) || (needEvenHeights && ((*cellHeight & 1) != 0)))) {
        --gridRows;
        *cellHeight = image.height / gridRows;
    }

    std::vector<testutil::avifImagePtr> cellImages;
    cellImages.reserve(gridCols * gridRows);
    for (uint32_t row = 0, iCell = 0; row < gridRows; ++row) {
        for (uint32_t col = 0; col < gridCols; ++col, ++iCell) {
            avifCropRect cell;
            cell.x = col * *cellWidth;
            cell.y = row * *cellHeight;
            cell.width = ((cell.x + *cellWidth) <= image.width) ? *cellWidth : (image.width - cell.x);
            cell.height = ((cell.y + *cellHeight) <= image.height) ? *cellHeight : (image.height - cell.y);
            cellImages.emplace_back(avifImageCreateEmpty(), avifImageDestroy);
            ASSERT_NE(cellImages.back(), nullptr);
            ASSERT_EQ(avifImageSetViewRect(cellImages.back().get(), &image, &cell), AVIF_RESULT_OK);
        }
    }

    testutil::avifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
    ASSERT_NE(encoder, nullptr);
    encoder->speed = AVIF_SPEED_FASTEST;
    std::vector<avifImage *> cellImagePtrs(cellImages.size()); // Just here to match libavif API.
    for (size_t i = 0; i < cellImages.size(); ++i) {
        cellImagePtrs[i] = cellImages[i].get();
    }
    ASSERT_EQ(avifEncoderAddImageGrid(encoder.get(), gridCols, gridRows, cellImagePtrs.data(), AVIF_ADD_IMAGE_FLAG_SINGLE), AVIF_RESULT_OK);
    ASSERT_EQ(avifEncoderFinish(encoder.get(), output), AVIF_RESULT_OK);
}

// Encodes the image to be decoded incrementally.
void encodeAsIncremental(const avifImage & image, bool flatCells, avifRWData * output, uint32_t * cellWidth, uint32_t * cellHeight)
{
    const uint32_t gridCols = image.width / 64; // 64px is the min cell width.
    const uint32_t gridRows = flatCells ? 1 : (image.height / 64);
    encodeAsGrid(image, (gridCols > 1) ? gridCols : 1, (gridRows > 1) ? gridRows : 1, output, cellWidth, cellHeight);
}

} // namespace

void encodeRectAsIncremental(const avifImage & image,
                             uint32_t width,
                             uint32_t height,
                             bool createAlphaIfNone,
                             bool flatCells,
                             avifRWData * output,
                             uint32_t * cellWidth,
                             uint32_t * cellHeight)
{
    avifImagePtr subImage(avifImageCreateEmpty(), avifImageDestroy);
    ASSERT_NE(subImage, nullptr);
    ASSERT_LE(width, image.width);
    ASSERT_LE(height, image.height);
    avifPixelFormatInfo info;
    avifGetPixelFormatInfo(image.yuvFormat, &info);
    const avifCropRect rect {
        /*x=*/((image.width - width) / 2) & ~info.chromaShiftX, /*y=*/((image.height - height) / 2) & ~info.chromaShiftX, width, height
    };
    ASSERT_EQ(avifImageSetViewRect(subImage.get(), &image, &rect), AVIF_RESULT_OK);
    if (createAlphaIfNone && !subImage->alphaPlane) {
        ASSERT_NE(image.yuvPlanes[AVIF_CHAN_Y], nullptr) << "No luma plane to simulate an alpha plane";
        subImage->alphaPlane = image.yuvPlanes[AVIF_CHAN_Y];
        subImage->alphaRowBytes = image.yuvRowBytes[AVIF_CHAN_Y];
        subImage->alphaPremultiplied = AVIF_FALSE;
        subImage->imageOwnsAlphaPlane = AVIF_FALSE;
    }
    encodeAsIncremental(*subImage, flatCells, output, cellWidth, cellHeight);
}

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

void decodeIncrementally(const avifRWData & encodedAvif,
                         bool isPersistent,
                         bool giveSizeHint,
                         bool useNthImageApi,
                         const avifImage & reference,
                         uint32_t cellHeight)
{
    // AVIF cells are at least 64 pixels tall.
    if (cellHeight != reference.height) {
        ASSERT_GE(cellHeight, 64u);
    }

    // Emulate a byte-by-byte stream.
    avifROPartialData data = { /*available=*/ { encodedAvif.data, 0 }, /*fullSize=*/encodedAvif.size };
    avifIO io = { /*destroy=*/nullptr, avifIOPartialRead,
                  /*write=*/nullptr,   giveSizeHint ? encodedAvif.size : 0,
                  isPersistent,        &data };

    testutil::avifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
    ASSERT_NE(decoder, nullptr);
    avifDecoderSetIO(decoder.get(), &io);
    decoder->allowIncremental = AVIF_TRUE;

    // Parsing is not incremental.
    avifResult parseResult = avifDecoderParse(decoder.get());
    while (parseResult == AVIF_RESULT_WAITING_ON_IO) {
        ASSERT_LT(data.available.size, data.fullSize) << "avifDecoderParse() returned WAITING_ON_IO instead of OK";
        data.available.size = data.available.size + 1;
        parseResult = avifDecoderParse(decoder.get());
    }
    ASSERT_EQ(parseResult, AVIF_RESULT_OK);

    // Decoding is incremental.
    uint32_t previouslyDecodedRowCount = 0;
    avifResult nextImageResult = useNthImageApi ? avifDecoderNthImage(decoder.get(), 0) : avifDecoderNextImage(decoder.get());
    while (nextImageResult == AVIF_RESULT_WAITING_ON_IO) {
        ASSERT_LT(data.available.size, data.fullSize)
            << (useNthImageApi ? "avifDecoderNthImage(0)" : "avifDecoderNextImage()") << " returned WAITING_ON_IO instead of OK";
        const uint32_t decodedRowCount = avifDecoderDecodedRowCount(decoder.get());
        ASSERT_GE(decodedRowCount, previouslyDecodedRowCount);
        const uint32_t minDecodedRowCount =
            getMinDecodedRowCount(reference.height, cellHeight, reference.alphaPlane != nullptr, data.available.size, data.fullSize);
        ASSERT_GE(decodedRowCount, minDecodedRowCount);
        comparePartialYUVA(reference, *decoder->image, decodedRowCount);

        previouslyDecodedRowCount = decodedRowCount;
        data.available.size = data.available.size + 1;
        nextImageResult = useNthImageApi ? avifDecoderNthImage(decoder.get(), 0) : avifDecoderNextImage(decoder.get());
    }
    ASSERT_EQ(nextImageResult, AVIF_RESULT_OK);
    ASSERT_EQ(data.available.size, data.fullSize);
    ASSERT_EQ(avifDecoderDecodedRowCount(decoder.get()), decoder->image->height);

    comparePartialYUVA(reference, *decoder->image, reference.height);
}

void decodeNonIncrementallyAndIncrementally(const avifRWData & encodedAvif, bool isPersistent, bool giveSizeHint, bool useNthImageApi, uint32_t cellHeight)
{
    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);

    decodeIncrementally(encodedAvif, isPersistent, giveSizeHint, useNthImageApi, *reference, cellHeight);
}

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

} // namespace testutil
} // namespace libavif
