#include <SDL3/SDL.h>
#include "registry.h"
#include "error.h"
#include <stdlib.h>

typedef ErrorContext *(*RegistryFuncPtr)(void);

void *sdl_calloc_always_fails(size_t a, size_t b)
{
    // This forces SDL to simulate an out of memory condition
    return NULL;
}

ErrorContext *test_registry_init(RegistryFuncPtr funcptr)
{
    SDL_malloc_func malloc_func;
    SDL_calloc_func calloc_func;
    SDL_realloc_func realloc_func;
    SDL_free_func free_func;
    
    SDL_GetMemoryFunctions(
	&malloc_func,
	&calloc_func,
	&realloc_func,
	&free_func
	);
    PREPARE_ERROR(errctx);
    ATTEMPT {
	SDL_SetMemoryFunctions(
	    malloc_func,
	    (SDL_calloc_func)&sdl_calloc_always_fails,
	    realloc_func,
	    free_func
	    );
	CATCH(errctx, funcptr());
    } CLEANUP {
	SDL_SetMemoryFunctions(
	    malloc_func,
	    calloc_func,
	    realloc_func,
	    free_func
	    );
    } PROCESS(errctx) {
    } FINISH(errctx, true);

    FAIL_RETURN(errctx, ERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation");
}

ErrorContext *test_registry_init_creation_failures(void)
{
    PREPARE_ERROR(errctx);
    ATTEMPT {
	CATCH(errctx, test_registry_init(&registry_init_actor));
    } CLEANUP {
    } PROCESS(errctx) {
    } HANDLE(errctx, ERR_NULLPOINTER) {
      printf("Sucess\n");
    } FINISH(errctx, true);

    ATTEMPT {
	CATCH(errctx, test_registry_init(&registry_init_sprite));
    } CLEANUP {
    } PROCESS(errctx) {
    } HANDLE(errctx, ERR_NULLPOINTER) {
      printf("Sucess\n");
    } FINISH(errctx, true);

    ATTEMPT {
	CATCH(errctx, test_registry_init(&registry_init_spritesheet));
    } CLEANUP {
    } PROCESS(errctx) {
    } HANDLE(errctx, ERR_NULLPOINTER) {
      printf("Sucess\n");
    } FINISH(errctx, true);

    ATTEMPT {
	CATCH(errctx, test_registry_init(&registry_init_character));
    } CLEANUP {
    } PROCESS(errctx) {
    } HANDLE(errctx, ERR_NULLPOINTER) {
      printf("Sucess\n");
    } FINISH(errctx, true);
    SUCCEED_RETURN(errctx);
}

int main(void)
{
    PREPARE_ERROR(errctx);
    ATTEMPT {
	CATCH(errctx, test_registry_init_creation_failures());
    } CLEANUP {
    } PROCESS(errctx) {
    } FINISH_NORETURN(errctx);


}
