// Copyright 2020 Joe Drago. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause

#include "testcase.h"

#include "compare.h"
#include "y4m.h"

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

static const char * choiceToString(avifCodecChoice choice)
{
    switch (choice) {
        case AVIF_CODEC_CHOICE_AUTO:
            return "auto";
        case AVIF_CODEC_CHOICE_AOM:
            return "aom";
        case AVIF_CODEC_CHOICE_DAV1D:
            return "dav1d";
        case AVIF_CODEC_CHOICE_LIBGAV1:
            return "libgav1";
        case AVIF_CODEC_CHOICE_RAV1E:
            return "rav1e";
    }
    return "unknown";
}

static avifCodecChoice stringToChoice(const char * str)
{
    if (!strcmp(str, "aom")) {
        return AVIF_CODEC_CHOICE_AOM;
    } else if (!strcmp(str, "dav1d")) {
        return AVIF_CODEC_CHOICE_DAV1D;
    } else if (!strcmp(str, "libgav1")) {
        return AVIF_CODEC_CHOICE_LIBGAV1;
    } else if (!strcmp(str, "rav1e")) {
        return AVIF_CODEC_CHOICE_RAV1E;
    }
    return AVIF_CODEC_CHOICE_AUTO;
}

TestCase * testCaseCreate(void)
{
    TestCase * tc = malloc(sizeof(TestCase));
    memset(tc, 0, sizeof(TestCase));
    return tc;
}

void testCaseDestroy(TestCase * tc)
{
    if (tc->name) {
        free(tc->name);
    }
    if (tc->inputFilename) {
        free(tc->inputFilename);
    }
    free(tc);
}

void testCaseSetInputFilename(TestCase * tc, const char * inputFilename)
{
    if (tc->inputFilename) {
        free(tc->inputFilename);
    }
    tc->inputFilename = strdup(inputFilename);
}

void testCaseGenerateName(TestCase * tc)
{
    char basenameBuffer[1024];
    if (tc->inputFilename) {
        strcpy(basenameBuffer, tc->inputFilename);
        char * dotLoc = strrchr(basenameBuffer, '.');
        if (dotLoc) {
            *dotLoc = 0;
        }
    } else {
        basenameBuffer[0] = 0;
    }

    char nameBuffer[1024];
    if (snprintf(nameBuffer,
                 sizeof(nameBuffer),
                 "%s_%s_to_%s_qp%d_%d_speed%d",
                 basenameBuffer,
                 choiceToString(tc->encodeChoice),
                 choiceToString(tc->decodeChoice),
                 tc->minQuantizer,
                 tc->maxQuantizer,
                 tc->speed) < 0) {
        nameBuffer[0] = 0;
    }
    nameBuffer[sizeof(nameBuffer) - 1] = 0;
    if (tc->name) {
        free(tc->name);
    }
    tc->name = strdup(nameBuffer);
}

static const char * jsonGetString(cJSON * parent, const char * key, const char * def)
{
    if (!parent || !cJSON_IsObject(parent)) {
        return def;
    }

    cJSON * childItem = cJSON_GetObjectItem(parent, key);
    if (!childItem || !cJSON_IsString(childItem)) {
        return def;
    }
    return childItem->valuestring;
}

static int jsonGetInt(cJSON * parent, const char * key, int def)
{
    if (!parent || !cJSON_IsObject(parent)) {
        return def;
    }

    cJSON * childItem = cJSON_GetObjectItem(parent, key);
    if (!childItem || !cJSON_IsNumber(childItem)) {
        return def;
    }
    return childItem->valueint;
}

static float jsonGetFloat(cJSON * parent, const char * key, float def)
{
    if (!parent || !cJSON_IsObject(parent)) {
        return def;
    }

    cJSON * childItem = cJSON_GetObjectItem(parent, key);
    if (!childItem || !cJSON_IsNumber(childItem)) {
        return def;
    }
    return (float)childItem->valuedouble;
}

static avifBool jsonGetBool(cJSON * parent, const char * key, avifBool def)
{
    if (!parent || !cJSON_IsObject(parent)) {
        return def;
    }

    cJSON * childItem = cJSON_GetObjectItem(parent, key);
    if (!childItem || !cJSON_IsBool(childItem)) {
        return def;
    }
    return (childItem->type == cJSON_True) ? AVIF_TRUE : AVIF_FALSE;
}

TestCase * testCaseFromJSON(cJSON * json)
{
    TestCase * tc = testCaseCreate();
    tc->name = strdup(jsonGetString(json, "name", "unknown"));
    tc->inputFilename = strdup(jsonGetString(json, "input", "unknown"));

    tc->encodeChoice = stringToChoice(jsonGetString(json, "enc", "aom"));
    tc->decodeChoice = stringToChoice(jsonGetString(json, "dec", "aom"));
    tc->minQuantizer = jsonGetInt(json, "minQP", 0);
    tc->maxQuantizer = jsonGetInt(json, "maxQP", 0);
    tc->speed = jsonGetInt(json, "speed", 0);
    tc->active = jsonGetBool(json, "active", AVIF_FALSE);

    tc->maxThreshold = jsonGetInt(json, "max", 0);
    tc->avgThreshold = jsonGetFloat(json, "avg", 0);
    return tc;
}

cJSON * testCaseToJSON(TestCase * tc)
{
    cJSON * json = cJSON_CreateObject();

    if (tc->name) {
        cJSON_AddStringToObject(json, "name", tc->name);
    }
    if (tc->inputFilename) {
        cJSON_AddStringToObject(json, "input", tc->inputFilename);
    }

    cJSON_AddStringToObject(json, "enc", choiceToString(tc->encodeChoice));
    cJSON_AddStringToObject(json, "dec", choiceToString(tc->decodeChoice));
    cJSON_AddNumberToObject(json, "minQP", tc->minQuantizer);
    cJSON_AddNumberToObject(json, "maxQP", tc->maxQuantizer);
    cJSON_AddNumberToObject(json, "speed", tc->speed);
    cJSON_AddBoolToObject(json, "active", tc->active);

    cJSON_AddNumberToObject(json, "max", tc->maxThreshold);
    cJSON_AddNumberToObject(json, "avg", tc->avgThreshold);
    return json;
}

int testCaseRun(TestCase * tc, const char * dataDir, avifBool generating)
{
    if (!tc->name || !tc->inputFilename) {
        return AVIF_FALSE;
    }

    char y4mFilename[2048];
    snprintf(y4mFilename, sizeof(y4mFilename), "%s/%s", dataDir, tc->inputFilename);
    y4mFilename[sizeof(y4mFilename) - 1] = 0;

    avifImage * image = avifImageCreateEmpty();
    if (!y4mRead(image, y4mFilename)) {
        avifImageDestroy(image);
        printf("ERROR[%s]: Can't read y4m: %s\n", tc->name, y4mFilename);
        return AVIF_FALSE;
    }

    avifBool result = AVIF_TRUE;
    avifRWData encodedData = AVIF_DATA_EMPTY;
    avifEncoder * encoder = NULL;
    avifDecoder * decoder = NULL;

    encoder = avifEncoderCreate();
    encoder->codecChoice = tc->encodeChoice;
    encoder->maxThreads = 4; // TODO: pick something better here
    if (avifEncoderWrite(encoder, image, &encodedData) != AVIF_RESULT_OK) {
        printf("ERROR[%s]: Encode failed\n", tc->name);
        result = AVIF_FALSE;
        goto cleanup;
    }

    decoder = avifDecoderCreate();
    decoder->codecChoice = tc->decodeChoice;
    avifResult decodeResult = avifDecoderParse(decoder, (avifROData *)&encodedData);
    if (decodeResult != AVIF_RESULT_OK) {
        printf("ERROR[%s]: Decode failed\n", tc->name);
        result = AVIF_FALSE;
        goto cleanup;
    }

    avifResult nextImageResult = avifDecoderNextImage(decoder);
    if (nextImageResult != AVIF_RESULT_OK) {
        printf("ERROR[%s]: NextImage failed\n", tc->name);
        result = AVIF_FALSE;
        goto cleanup;
    }

    ImageComparison ic;
    if (!compareYUVA(&ic, image, decoder->image)) {
        printf("ERROR[%s]: compare bailed out\n", tc->name);
        result = AVIF_FALSE;
        goto cleanup;
    }

    if (generating) {
        int maxThreshold = ic.maxDiff;
        if (maxThreshold > 0) {
            // Not lossless, give one more codepoint of wiggle room
            ++maxThreshold;
        }
        float avgThreshold = ic.avgDiff + 0.25f;

        tc->maxThreshold = maxThreshold;
        tc->avgThreshold = avgThreshold;
        printf("Generated[%s]: Thresholds - Max %d, Avg %f\n", tc->name, tc->maxThreshold, tc->avgThreshold);
    } else {
        if (ic.maxDiff > tc->maxThreshold) {
            printf("ERROR[%s]: max diff threshold exceeded: %d > %d\n", tc->name, ic.maxDiff, tc->maxThreshold);
            result = AVIF_FALSE;
            goto cleanup;
        }
        if (ic.avgDiff > tc->avgThreshold) {
            printf("FAILED[%s]: avg diff threshold exceeded: %f > %f\n", tc->name, ic.avgDiff, tc->avgThreshold);
            result = AVIF_FALSE;
            goto cleanup;
        }
        printf("OK[%s]\n", tc->name);
    }

cleanup:
    if (decoder) {
        avifDecoderDestroy(decoder);
    }
    avifRWDataFree(&encodedData);
    if (encoder) {
        avifEncoderDestroy(encoder);
    }
    avifImageDestroy(image);
    (void)generating;
    return result;
}
