
#include "list.h"
#include "bomber.h"
#include "utils.h"

typedef union genericlistitem genericlistitem;
union genericlistitem {
	genericlistitem* next;
	listhead list;
	bomb b;
	flame f;
	brickdecay bc;
	player p;
	bonustile bt;
	generic g;
};

/* doesn't use prev link */
static genericlistitem* things = 0;
static genericlistitem* free_things;

static int count_used = 0;

void alloc_things(void) {
	int i;

	if (!things) {
		things = calloc(MAXTHINGS, sizeof(genericlistitem));
	} else {
		memset(things, 0, MAXTHINGS * sizeof(genericlistitem));
	}
	if (!things) nomem("Trying to allocate thing memory");

	for (i = 0; i < MAXTHINGS - 1; ++i) { things[i].next = &things[i + 1]; }
	things[i].next = 0;
	free_things = things;
	count_used = 0;
}

void* _allocentry(size_t size) {
	genericlistitem* entry = free_things;

	if (size > sizeof(genericlistitem)) return 0;

	if (free_things) {
		count_used++;
		free_things = free_things->next;
		memset(entry, 0, sizeof(genericlistitem));
	}
	return entry;
}

void freeentry(void* ptr) {
	genericlistitem* entry = ptr;
	entry->next = free_things;
	free_things = entry;
	count_used--;
}

void list_add_tail(listhead* head, listhead* entry) {
	entry->next = head;
	entry->prev = head->prev;
	head->prev->next = entry;
	head->prev = entry;
}

void list_del(listhead* entry) {
	entry->next->prev = entry->prev;
	entry->prev->next = entry->next;
	entry->next = entry->prev = entry;
}

void list_init_head(listhead* head) {
	head->next = head;
	head->prev = head;
}

void things_list_clear(listhead* head) {
	genericlistitem* entry;

	while (head->next != head) {
		entry = container_of(head->next, __typeof__(*entry), list);
		list_del(head->next);
		freeentry(entry);
	}
}
