#include "allocator_impl.h"

static memory_stats	stats;

void	memory_system_init() {
	stats = (memory_stats){0};
}

memory_page*	memory_system_alloc(size_t nmemb, size_t size) {
	memory_page* memory;
	memory = malloc(sizeof(memory_page));
	assert(memory);
	memory->size = 1;
	memory->ptr = aligigned_alloc(size, nmemb * size);


	stats.current_allocated += size;
	stats.total_allocated += size;
	stats.total_allocation ++;
	return (memory);
}

void	memory_system_free(memory_page* page) {

}

void	memory_system_shutdown() {
	if (stats.current_allocated != 0) {
		printf("WARNING: %.2lld Mb got leaked\n", stats.current_allocated / 1048576);
	}
}

void	memory_system_print() {
	printf("INFO: allocation_count: %i , total_allocated: %.2lld Mb, total_freed: %.2lld Mb, current_allocated: %2lld Mb\n",
		stats.total_allocation, stats.total_allocated / 1048576, stats.total_freed / 1048576, stats.current_allocated / 1048576);
}

#include "allocator_impl.h"


// typedef struct pool_block_s {
//     struct pool_block_s *next;
// } pool_block_t;

// typedef struct {
//     pool_block_t *free_list;
//     void *memory;
//     size_t block_size;
//     size_t pool_size;
//     size_t alignment;
// } pool_allocator_t;

// pool_allocator_t *haven_pool_create(size_t block_size, size_t count, size_t alignment) {
//     pool_allocator_t *pool = malloc(sizeof(pool_allocator_t));

//     // Adjust block size for alignment and ensure it can hold a pointer
//     size_t aligned_size = ((block_size + sizeof(pool_block_t) - 1) / alignment + 1) * alignment;
//     pool->block_size = aligned_size;
//     pool->pool_size = aligned_size * count;
//     pool->alignment = alignment;

//     // Allocate aligned memory for the pool
//     pool->memory = _aligned_malloc(alignment, pool->pool_size);
//     pool->free_list = NULL;

//     // Initialize the free list
//     char *block = (char*)pool->memory;
//     for (size_t i = 0; i < count; i++) {
//         pool_block_t *node = (pool_block_t*)block;
//         node->next = pool->free_list;
//         pool->free_list = node;
//         block += aligned_size;
//     }

//     return pool;
// }

// void *haven_pool_alloc(pool_allocator_t *pool) {
//     if (!pool->free_list) return NULL;

//     pool_block_t *block = pool->free_list;
//     pool->free_list = block->next;
//     return block;
// }

// void haven_pool_free(pool_allocator_t *pool, void *ptr) {
//     if (!ptr || ptr < pool->memory || ptr >= (char*)pool->memory + pool->pool_size) return;

//     pool_block_t *block = (pool_block_t*)ptr;
//     block->next = pool->free_list;
//     pool->free_list = block;
// }

// void haven_pool_destroy(pool_allocator_t *pool) {
//     if (pool) {
//         free(pool->memory);
//         free(pool);
//     }
// }

#include "allocator_impl.h"

#define STACK_SIZE 67108864 //64Mb

static allocator_stack	stacks[2];
static uint8_t		current;

void	*allocator_stack_alloc(size_t size, size_t alignment) {
	uintptr_t raw_addr = 0x00;
	void* aligned_ptr = 0x00;
	size_t padding = 0;

	raw_addr = (uintptr_t)(stacks[current].base + stacks[current].offset);
	assert(raw_addr);

	padding = (alignment - (raw_addr % alignment)) % alignment;

	if (stacks[current].offset + size + padding > stacks[current].size) {
		return NULL;
	}

	aligned_ptr = (void*)(raw_addr + padding);
	stacks[current].offset += size + padding;
	return aligned_ptr;
}

void	allocator_stack_swap(void) {
	stacks[current].offset = 0;
	current ^= 1;
}

void	allocator_stack_init(void) {

}

void	allocator_stack_delete(void) {

}
