#include "chunk.h"
#include "align.h"
#include "print.h"

int get_unused_chunk(chunk_t *root, size_t size, chunk_t *result)
{
    void** current = root->current;

    while (current != NULL)
    {
        if ((bool) current[CHUNK_IS_USED_POS] == true)
            continue;
        if ((size_t) current[CHUNK_SIZE_POS] >= size)
        {
            chunk_read(current, result);
            return 0;
        }
        current = current[CHUNK_NEXT_POS];
    }
    return 1;
}

void chunk_merge(chunk_t *first, chunk_t *second)
{
#ifndef DEBUG
    if (first->block_id != second->block_id)
        putstr("Attempt merge two chunk on different block\n");
#endif        
	first->size = first->size + second->size + CHUNK_SIZE + ALIGN_MARGING - get_align_increment(first->next);
	first->next = second->next;
}

int chunk_split(chunk_t *chunk, chunk_t *new_chunk, size_t new_size)
{
	// NOT ENOUGH SIZE TO BE SPLITTED
	if (chunk->size + 1 < new_size + CHUNK_SIZE + get_align_increment(chunk->current + CHUNK_SIZE))
		return 1;
	
	void *new_chunk_pos = chunk->data_start + new_size;

	chunk_init(new_chunk, chunk->size - new_size - CHUNK_SIZE - get_align_increment(new_chunk_pos + CHUNK_SIZE), chunk->block_id, chunk->current, new_chunk_pos, chunk->next, true);
	chunk_init(chunk, new_size, chunk->block_id, chunk->prev, chunk->current, new_chunk->current, false);

    return 0;
}

void chunk_iter(chunk_t *root, void (*f)(chunk_t*))
{
    chunk_t *current = root;

    while (current)
    {
        f(current);
        if (current->next == NULL)
            break;
        chunk_read(current->next, current);
    }
}