#include "jnet.h"

// gcc -o test_ll test_ll.c

/*
 * Linked List implementation -- begin
 */
static JNet_LinkedList_Entry *linked_list_init(JNet_LinkedList_Entry *linked_list_head) {
	linked_list_head->prev_entry = linked_list_head;
	linked_list_head->next_entry = linked_list_head;

	linked_list_head->data = (char *) NULL;

	linked_list_head->entry_count = 0;
	linked_list_head->read_next_entry = NULL;

	return linked_list_head;
}

static char *linked_list_insert_at_tail(JNet_LinkedList_Entry *linked_list_head, char *data) {
	JNet_LinkedList_Entry *new_entry;

	new_entry = (JNet_LinkedList_Entry *) malloc(sizeof(JNet_LinkedList_Entry));

	new_entry->prev_entry = linked_list_head->prev_entry;
	new_entry->next_entry = linked_list_head;
	linked_list_head->prev_entry->next_entry = new_entry; 
	linked_list_head->prev_entry = new_entry; 

	new_entry->data = data;
	new_entry->entry_count = NOT_USED;

	linked_list_head->entry_count++;
	linked_list_head->read_next_entry = NULL;

	return data;
}

static char *linked_list_remove_from_head(JNet_LinkedList_Entry *linked_list_head) {
	JNet_LinkedList_Entry *removing_entry;
	char *data;

	if(linked_list_head->entry_count <= 0) {
		return NULL;
	}

	removing_entry = linked_list_head->next_entry;
	data = removing_entry->data;

	removing_entry->next_entry->prev_entry = linked_list_head;
	linked_list_head->next_entry = removing_entry->next_entry; 

	linked_list_head->entry_count--;
	linked_list_head->read_next_entry = NULL;

	free(removing_entry);	

	return data;
}

static char *linked_list_get_next(JNet_LinkedList_Entry *linked_list_head) {
	JNet_LinkedList_Entry *read_next_entry;

	if(linked_list_head->entry_count <= 0) {
		return NULL;
	}
 
	if(linked_list_head->read_next_entry == NULL) {
		linked_list_head->read_next_entry 
				= linked_list_head->next_entry; 
		return linked_list_head->read_next_entry->data;
	}

	if(linked_list_head->read_next_entry->next_entry == linked_list_head) {
		linked_list_head->read_next_entry = NULL;
		return NULL;
	}

	read_next_entry = linked_list_head->read_next_entry->next_entry;
	linked_list_head->read_next_entry = read_next_entry;
	return read_next_entry->data;
}

/*
 * Linked List implementation -- end
 */

JNet_LinkedList_Entry ll_list;
JNet_Filter *filter;

int main(int argc, char *argv[])
{
	linked_list_init(&ll_list);

	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 5;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);

	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 10;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);

	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 15;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);

	printf("entries before del %d \n", ll_list.entry_count);

	filter = (JNet_Filter *) linked_list_remove_from_head(&ll_list);
	printf("del entry %d \n", filter->judgment);
	free((char *) filter);

	printf("entries after del %d \n", ll_list.entry_count);



	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 20;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);

	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 25;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);




	printf("entries before del %d \n", ll_list.entry_count);

	filter = (JNet_Filter *) linked_list_remove_from_head(&ll_list);
	printf("del entry %d \n", filter->judgment);
	free((char *) filter);

	filter = (JNet_Filter *) linked_list_remove_from_head(&ll_list);
	printf("del entry %d \n", filter->judgment);
	free((char *) filter);

	printf("entries after del %d \n", ll_list.entry_count);





	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 30;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);

	filter = (JNet_Filter *) malloc(sizeof(JNet_Filter));
	filter->judgment = 35;
	linked_list_insert_at_tail(&ll_list, (char *) filter);
	printf("add entry %d \n", filter->judgment);

	printf("entries %d \n", ll_list.entry_count);

	while((filter = (JNet_Filter *) linked_list_get_next(&ll_list)) != NULL) {
		printf(" get - judgment %d \n", filter->judgment);
	}

	while((filter = (JNet_Filter *) linked_list_remove_from_head(&ll_list)) != NULL) {
		printf(" del - judgment %d \n", filter->judgment);
		free((char *) filter);
	}

	exit(0);


}
