#include <SDL2/SDL_error.h>
#include <unistd.h>
#include "renderer.h"
#include "scaller.h"
#include "text.h"
#include <SDL2/SDL_log.h>

#define FONT_CACHE_SIZE 100
#define MAX_TEXT_SIZE 10000

typedef struct FontCacheObject {
    char* file;
    int size;
    TTF_Font* font;
} FontCacheObject_t;

static FontCacheObject_t fontCache[FONT_CACHE_SIZE];
static unsigned fontCacheSize = 0;

void text_freeFontCache(void){
    for(unsigned i = 0; i < fontCacheSize; ++i){
        free(fontCache[i].file);
        TTF_CloseFont(fontCache[i].font);
    }
    fontCacheSize = 0;
}

int text_renderText(RenderObject_t* renderObject, int z, float scale, SDL_Color color, const char* fontFilename, int fontSize, char* format, ...) {
    if(access(fontFilename, F_OK) != 0) {
        fprintf(stderr, "Font file not found: %s\n", fontFilename);
        return -1;
    }

    TTF_Font* font = NULL;
    for(unsigned i = 0; i < fontCacheSize; ++i){
        if(strcmp(fontCache[i].file, fontFilename) == 0 && fontCache[i].size == fontSize){
            font = fontCache[i].font;
            break;
        }
    }
    if(font == NULL) {
        font = TTF_OpenFont(fontFilename, fontSize);
        if(font == NULL) {
            SDL_LogError(SDL_LOG_PRIORITY_ERROR, "TTF_OpenFont");
            fprintf(stderr, "Error while opening font: %s\n", SDL_GetError());
            return -1;
        }
        FontCacheObject_t fontCacheObject;
        fontCacheObject.file = (char*)malloc(strlen(fontFilename) + 1);
        strcpy(fontCacheObject.file, fontFilename);
        fontCacheObject.size = fontSize;
        fontCacheObject.font = font;
        fontCache[fontCacheSize] = fontCacheObject;
        ++fontCacheSize;
    }

    char text[MAX_TEXT_SIZE];
    va_list args;

	memset(&text, '\0', sizeof(text));

	va_start(args, format);
	vsprintf(text, format, args);
	va_end(args);

    MonitorSize_t monitor = renderer_getMonitorSize();
    SDL_Surface* surface = TTF_RenderText_Blended_Wrapped(font, text, color, monitor.width);

    int h, w;

    TTF_SizeText(font, text, &w, &h);

    renderObject->z = z;
    renderObject->angle_degre = 0;
    renderObject->surface = surface;

    scaller(surface, scale, &renderObject->width, &renderObject->height);
    return 0;
}
