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

#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "avif/avif.h"

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

// ICC color profiles are not checked by libavif so the content does not matter.
// This is a truncated widespread ICC color profile.
static const uint8_t sampleICC[] = { 0x00, 0x00, 0x02, 0x0c, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00,
                                     0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20 };
static const size_t sampleICCSize = sizeof(sampleICC) / sizeof(sampleICC[0]);

// Exif bytes are partially checked by libavif. This is a truncated widespread Exif metadata chunk.
static const uint8_t sampleExif[] = { 0xff, 0x1,  0x45, 0x78, 0x69, 0x76, 0x32, 0xff, 0xe1, 0x12, 0x5a, 0x45,
                                      0x78, 0x69, 0x66, 0x0,  0x0,  0x49, 0x49, 0x2a, 0x0,  0x8,  0x0,  0x0 };
static const size_t sampleExifSize = sizeof(sampleExif) / sizeof(sampleExif[0]);

// XMP bytes are not checked by libavif so the content does not matter.
// This is a truncated widespread XMP metadata chunk.
static const uint8_t sampleXMP[] = { 0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65,
                                     0x67, 0x69, 0x6e, 0x3d, 0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64 };
static const size_t sampleXMPSize = sizeof(sampleXMP) / sizeof(sampleXMP[0]);

//------------------------------------------------------------------------------
// TODO: Move these functions to a tests/common/helper.c shared with avifgridapitest.c

// Fills a plane with a repeating gradient.
static void fillPlane(int width, int height, int depth, uint8_t * row, uint32_t rowBytes)
{
    assert((depth == 8) || (depth == 10) || (depth == 12)); // Values allowed by AV1.
    const int maxValuePlusOne = 1 << depth;
    for (int y = 0; y < height; ++y) {
        if (depth == 8) {
            memset(row, y % maxValuePlusOne, width);
        } else {
            for (int x = 0; x < width; ++x) {
                ((uint16_t *)row)[x] = (uint16_t)(y % maxValuePlusOne);
            }
        }
        row += rowBytes;
    }
}

// Creates an image where the pixel values are defined but do not matter.
// Returns false in case of memory failure.
static avifBool createImage(int width, int height, int depth, avifPixelFormat yuvFormat, avifBool createAlpha, avifImage ** image)
{
    *image = avifImageCreate(width, height, depth, yuvFormat);
    if (!*image) {
        printf("ERROR: avifImageCreate() failed\n");
        return AVIF_FALSE;
    }
    avifImageAllocatePlanes(*image, createAlpha ? AVIF_PLANES_ALL : AVIF_PLANES_YUV);

    avifPixelFormatInfo formatInfo;
    avifGetPixelFormatInfo((*image)->yuvFormat, &formatInfo);
    uint32_t uvWidth = ((*image)->width + formatInfo.chromaShiftX) >> formatInfo.chromaShiftX;
    uint32_t uvHeight = ((*image)->height + formatInfo.chromaShiftY) >> formatInfo.chromaShiftY;

    const int planeCount = formatInfo.monochrome ? 1 : AVIF_PLANE_COUNT_YUV;
    for (int plane = 0; plane < planeCount; ++plane) {
        fillPlane((plane == AVIF_CHAN_Y) ? (*image)->width : uvWidth,
                  (plane == AVIF_CHAN_Y) ? (*image)->height : uvHeight,
                  (*image)->depth,
                  (*image)->yuvPlanes[plane],
                  (*image)->yuvRowBytes[plane]);
    }

    if (createAlpha) {
        fillPlane((*image)->width, (*image)->height, (*image)->depth, (*image)->alphaPlane, (*image)->alphaRowBytes);
    }
    return AVIF_TRUE;
}

static avifBool createImage1x1(avifImage ** image)
{
    return createImage(/*width=*/1, /*height=*/1, /*depth=*/10, AVIF_PIXEL_FORMAT_YUV444, /*createAlpha=*/AVIF_TRUE, image);
}

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

// Encodes the image. Returns false in case of failure.
static avifBool encode(const avifImage * image, avifRWData * output)
{
    avifBool success = AVIF_FALSE;
    avifEncoder * encoder = avifEncoderCreate();
    if (!encoder) {
        printf("ERROR: avifEncoderCreate() failed\n");
        goto cleanup;
    }
    encoder->speed = AVIF_SPEED_FASTEST;
    if (avifEncoderWrite(encoder, image, output) != AVIF_RESULT_OK) {
        printf("ERROR: avifEncoderWrite() failed\n");
        goto cleanup;
    }

    success = AVIF_TRUE;
cleanup:
    if (encoder) {
        avifEncoderDestroy(encoder);
    }
    return success;
}

// Decodes the data. Returns false in case of failure.
static avifBool decode(const avifRWData * encodedAvif, avifImage ** image)
{
    avifBool success = AVIF_FALSE;
    *image = avifImageCreateEmpty();
    avifDecoder * const decoder = avifDecoderCreate();
    if (!*image || !decoder) {
        printf("ERROR: memory allocation failed\n");
        goto cleanup;
    }
    if (avifDecoderReadMemory(decoder, *image, encodedAvif->data, encodedAvif->size) != AVIF_RESULT_OK) {
        printf("ERROR: avifDecoderReadMemory() failed\n");
        goto cleanup;
    }
    success = AVIF_TRUE;
cleanup:
    if (decoder) {
        avifDecoderDestroy(decoder);
    }
    return success;
}

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

// Returns true if the decoded output metadata matches the input metadata.
static avifBool metadataIsEqual(const avifRWData * inputItem, const avifRWData * outputItem)
{
    return (outputItem->size == inputItem->size) && (memcmp(outputItem->data, inputItem->data, inputItem->size) == 0);
}

// Encodes, decodes then compares the metadata of the input and decoded images.
static avifBool encodeDecode(const avifImage * image)
{
    avifBool success = AVIF_FALSE;
    avifRWData encodedAvif = AVIF_DATA_EMPTY;
    avifImage * decodedImage = NULL;
    if (!encode(image, &encodedAvif)) {
        goto cleanup;
    }
    if (!decode(&encodedAvif, &decodedImage)) {
        goto cleanup;
    }

    if (!metadataIsEqual(&image->icc, &decodedImage->icc)) {
        printf("ERROR: icc mismatch\n");
        goto cleanup;
    }
    if (!metadataIsEqual(&image->exif, &decodedImage->exif)) {
        printf("ERROR: Exif metadata mismatch\n");
        goto cleanup;
    }
    if (!metadataIsEqual(&image->xmp, &decodedImage->xmp)) {
        printf("ERROR: XMP metadata mismatch\n");
        goto cleanup;
    }
    success = AVIF_TRUE;
cleanup:
    avifRWDataFree(&encodedAvif);
    if (decodedImage) {
        avifImageDestroy(decodedImage);
    }
    return success;
}

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

// Encodes, decodes then verifies that the output metadata matches the input
// metadata defined by the arguments.
static avifBool encodeDecodeMetadataItems(avifBool useICC, avifBool useExif, avifBool useXMP)
{
    avifBool success = AVIF_FALSE;
    avifImage * image = NULL;
    if (!createImage1x1(&image)) {
        goto cleanup;
    }

    if (useICC) {
        avifImageSetProfileICC(image, sampleICC, sampleICCSize);
    }
    if (useExif) {
        avifImageSetMetadataExif(image, sampleExif, sampleExifSize);
    }
    if (useXMP) {
        avifImageSetMetadataXMP(image, sampleXMP, sampleXMPSize);
    }

    if (!encodeDecode(image)) {
        goto cleanup;
    }
    success = AVIF_TRUE;
cleanup:
    if (image) {
        avifImageDestroy(image);
    }
    return success;
}

int main(void)
{
    if (!encodeDecodeMetadataItems(/*useICC=*/AVIF_TRUE, /*useExif=*/AVIF_FALSE, /*useXMP=*/AVIF_FALSE)) {
        return EXIT_FAILURE;
    }
    if (!encodeDecodeMetadataItems(/*useICC=*/AVIF_FALSE, /*useExif=*/AVIF_TRUE, /*useXMP=*/AVIF_FALSE)) {
        return EXIT_FAILURE;
    }
    if (!encodeDecodeMetadataItems(/*useICC=*/AVIF_FALSE, /*useExif=*/AVIF_FALSE, /*useXMP=*/AVIF_TRUE)) {
        return EXIT_FAILURE;
    }
    // TODO: Negative test
    // TODO: Multi xmp test
    printf("Test passed.\n");
    return EXIT_SUCCESS;
}
