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

#include "avif/internal.h"

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

void avifIODestroy(avifIO * io)
{
    if (io && io->destroy) {
        io->destroy(io);
    }
}

// --------------------------------------------------------------------------------------
// avifIOMemoryReader

typedef struct avifIOMemoryReader
{
    avifIO io; // this must be the first member for easy casting to avifIO*
    avifROData rodata;
} avifIOMemoryReader;

static avifResult avifIOMemoryReaderRead(struct avifIO * io, uint32_t readFlags, uint64_t offset, size_t size, avifROData * out)
{
    // printf("avifIOMemoryReaderRead offset %" PRIu64 " size %zu\n", offset, size);

    if (readFlags != 0) {
        // Unsupported readFlags
        return AVIF_RESULT_IO_ERROR;
    }

    avifIOMemoryReader * reader = (avifIOMemoryReader *)io;

    // Sanitize/clamp incoming request
    if (offset > reader->rodata.size) {
        // The offset is past the end of the buffer.
        return AVIF_RESULT_IO_ERROR;
    }
    uint64_t availableSize = reader->rodata.size - offset;
    if (size > availableSize) {
        size = (size_t)availableSize;
    }

    out->data = reader->rodata.data + offset;
    out->size = size;
    return AVIF_RESULT_OK;
}

static void avifIOMemoryReaderDestroy(struct avifIO * io)
{
    avifFree(io);
}

avifIO * avifIOCreateMemoryReader(const uint8_t * data, size_t size)
{
    avifIOMemoryReader * reader = avifAlloc(sizeof(avifIOMemoryReader));
    if (reader == NULL) {
        return NULL;
    }
    memset(reader, 0, sizeof(avifIOMemoryReader));
    reader->io.destroy = avifIOMemoryReaderDestroy;
    reader->io.read = avifIOMemoryReaderRead;
    reader->io.sizeHint = size;
    reader->io.persistent = AVIF_TRUE;
    reader->rodata.data = data;
    reader->rodata.size = size;
    return (avifIO *)reader;
}

// --------------------------------------------------------------------------------------
// avifIOFileReader

typedef struct avifIOFileReader
{
    avifIO io; // this must be the first member for easy casting to avifIO*
    avifRWData buffer;
    FILE * f;
} avifIOFileReader;

static avifResult avifIOFileReaderRead(struct avifIO * io, uint32_t readFlags, uint64_t offset, size_t size, avifROData * out)
{
    // printf("avifIOFileReaderRead offset %" PRIu64 " size %zu\n", offset, size);

    if (readFlags != 0) {
        // Unsupported readFlags
        return AVIF_RESULT_IO_ERROR;
    }

    avifIOFileReader * reader = (avifIOFileReader *)io;

    // Sanitize/clamp incoming request
    if (offset > reader->io.sizeHint) {
        // The offset is past the EOF.
        return AVIF_RESULT_IO_ERROR;
    }
    uint64_t availableSize = reader->io.sizeHint - offset;
    if (size > availableSize) {
        size = (size_t)availableSize;
    }

    if (size > 0) {
        if (offset > LONG_MAX) {
            return AVIF_RESULT_IO_ERROR;
        }
        if (reader->buffer.size < size) {
            AVIF_CHECKRES(avifRWDataRealloc(&reader->buffer, size));
        }
        if (fseek(reader->f, (long)offset, SEEK_SET) != 0) {
            return AVIF_RESULT_IO_ERROR;
        }
        size_t bytesRead = fread(reader->buffer.data, 1, size, reader->f);
        if (size != bytesRead) {
            if (ferror(reader->f)) {
                return AVIF_RESULT_IO_ERROR;
            }
            size = bytesRead;
        }
    }

    out->data = reader->buffer.data;
    out->size = size;
    return AVIF_RESULT_OK;
}

static void avifIOFileReaderDestroy(struct avifIO * io)
{
    avifIOFileReader * reader = (avifIOFileReader *)io;
    fclose(reader->f);
    avifRWDataFree(&reader->buffer);
    avifFree(io);
}

avifIO * avifIOCreateFileReader(const char * filename)
{
    FILE * f = fopen(filename, "rb");
    if (!f) {
        return NULL;
    }

    fseek(f, 0, SEEK_END);
    long fileSize = ftell(f);
    if (fileSize < 0) {
        fclose(f);
        return NULL;
    }
    fseek(f, 0, SEEK_SET);

    avifIOFileReader * reader = avifAlloc(sizeof(avifIOFileReader));
    if (!reader) {
        fclose(f);
        return NULL;
    }
    memset(reader, 0, sizeof(avifIOFileReader));
    reader->f = f;
    reader->io.destroy = avifIOFileReaderDestroy;
    reader->io.read = avifIOFileReaderRead;
    reader->io.sizeHint = (uint64_t)fileSize;
    reader->io.persistent = AVIF_FALSE;
    if (avifRWDataRealloc(&reader->buffer, 1024) != AVIF_RESULT_OK) {
        avifFree(reader);
        fclose(f);
        return NULL;
    }
    return (avifIO *)reader;
}
