#include "arc/std/io.h"

#include "arc/std/errno.h"
#include "arc/std/string.h"
#include <stdio.h>
#include <stdlib.h>

void ARC_IO_ReadFileToUint8t(ARC_String *path, uint8_t **data, uint64_t *length){
    FILE *file = fopen(path->data, "rb");
    if(!file){
        arc_errno = ARC_ERRNO_NULL;
        ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_IO_FileToStr(ARC_String *path, ARC_String **data), could not open file \"%s\"", path->data);
        *length = 0;
        *data = NULL;
        return;
    }

    fseek(file, 0L, SEEK_END);
    *length = ftell(file);
    rewind(file);

    *data = (uint8_t *) calloc(1, *length + 1);
    if(*data == NULL){
        fclose(file);
        arc_errno = ARC_ERRNO_NULL;
        ARC_DEBUG_LOG_ERROR("ARC_IO_FileToStr(ARC_String *path, ARC_String **data), file data is NULL");
        *length = 0;
        return;
    }

    if(1 != fread(*data, *length, 1, file)){
        fclose(file);
        arc_errno = ARC_ERRNO_COPY;
        ARC_DEBUG_LOG_ERROR("ARC_IO_FileToStr(ARC_String *path, ARC_String **data), could not copy file data");
        *length = 0;
        *data = NULL;
        return;
    }

    fclose(file);
}

void ARC_IO_FileToStr(ARC_String *path, ARC_String **data){
    FILE *file = fopen(path->data, "rb");
    if(!file){
        arc_errno = ARC_ERRNO_NULL;
        ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_IO_FileToStr(ARC_String *path, ARC_String **data), could not open file \"%s\"", path->data);
        return;
    }

    fseek(file, 0L, SEEK_END);
    uint64_t length = ftell(file);
    rewind(file);

    char *fileData = (char *) calloc(1, length + 1);
    if(fileData == NULL){
        fclose(file);
        arc_errno = ARC_ERRNO_NULL;
        ARC_DEBUG_LOG_ERROR("ARC_IO_FileToStr(ARC_String *path, ARC_String **data), file data is NULL");
        *data = NULL;
        return;
    }

    if(1 != fread(fileData, length, 1, file)){
        fclose(file);
        arc_errno = ARC_ERRNO_COPY;
        ARC_DEBUG_LOG_ERROR("ARC_IO_FileToStr(ARC_String *path, ARC_String **data), could not copy file data");
        *data = NULL;
        return;
    }

    fclose(file);
    ARC_String_Create(data, fileData, length);
    free(fileData);
}

void ARC_IO_WriteStrToFile(ARC_String *path, ARC_String *data){
    FILE *file = fopen(path->data, "wb");
    if(!file){
        arc_errno = ARC_ERRNO_NULL;
        ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_IO_WriteStrToFile(ARC_String *path, ARC_String *data), could not open file \"%s\"", path->data);
        return;
    }

    if(1 != fwrite(data->data, data->length, 1, file)){
        fclose(file);
        arc_errno = ARC_ERRNO_COPY;
        ARC_DEBUG_LOG_ERROR("ARC_IO_WriteStrToFile(ARC_String *path, ARC_String **data), could not write file data");
        return;
    }

    fclose(file);
}