// 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_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, "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;
}
