#include "bucketlist.h"
#include <stdlib.h>
#include <stdio.h>	/*DEBUG*/

void bl_init(bucketlist* list)
{
	list->head = NULL;
	list->tail = NULL;
	list->size = 0;
	return;
}


int bl_pushBack(bucketlist* list, int key, int val)
{
	int oldKey;
	bucketlistnode * newnode;
		

	// let no other nodes with this key remain
	oldKey = bl_deleteNodeWithKey(list, key);

	newnode = (bucketlistnode *) malloc(sizeof(bucketlistnode));
	if (newnode == NULL) return 0;  /* check malloc */

	newnode->key = key;
	newnode->val = val;
	newnode->next = NULL;
	newnode->last = list->tail;

	if (list->tail == NULL)
	{	/* no nodes yet */
		list->head = newnode;
		list->tail = newnode;
	}
	else
	{
		// now insert at end
		list->tail->next = newnode;
		list->tail = newnode;
	}
	list->size++;
	
	return (oldKey)?2:1;
}

bucketlistreturnval* bl_getNodeAt(bucketlist list, int index)
{
	bucketlistreturnval * retStatus = NULL;
	bucketlistnode * retNode;
	int i;
	
	retStatus = (bucketlistreturnval*) malloc(sizeof(bucketlistreturnval));
	if (retStatus == NULL) return NULL;   /* sanity check */
	if (index > list.size - 1)
	{
		retStatus->success = 0;
		return retStatus;
	}

	if ( (list.size > 1) && (index + 1 > list.size / 2))
	{	// search from tail backward
		retNode = list.tail;
		for (i = list.size - 1; i > index; i--)
		{
			retNode = retNode->last;
		}
	}
	else
	{
		// search from head forward
		retNode = list.head;
		for(i = 0; i < index; i++)
		{
			retNode = retNode->next;
		}
	}
	
	retStatus->success = 1;
	retStatus->val = retNode->val;
	retStatus->key = retNode->key;
	return retStatus;
}


bucketlistreturnval* bl_findNodeWithKey(bucketlist list, int key)
{
	bucketlistreturnval * retStatus = NULL;
	bucketlistnode * retNode;

	retStatus = (bucketlistreturnval*) malloc(sizeof(bucketlistreturnval));
	if (retStatus == NULL) return NULL;   /* sanity check */
	if (list.head == NULL) 
	{
		retStatus->success = 0;
		return retStatus;
	}
	// search from head forward
	retNode = list.head;
	do
	{
		if (retNode->key == key)
		{
			retStatus->success = 1;
			retStatus->key = key;
			retStatus->val = retNode->val;
			return retStatus;
		}
		retNode = retNode->next;
	} while (retNode != NULL);

	retStatus->success = 0;
	return retStatus;
}

int bl_deleteNodeAt(bucketlist * list, int index)
{
	bucketlistnode * deleteNode = NULL;
	bucketlistnode * prevNode = NULL;
	int i;

	/* sanity check */
	if (list == NULL || index > list->size)
		return 0;
	if ( (list->size > 1) && (index + 1 > list->size / 2) )
	{
		/* start at tail and search backward */
		deleteNode = list->tail;
		for (i = list->size - 1; i > index; i--)
		{
			deleteNode = deleteNode->last;
		}
	}
	else
	{	/* start at head and search forward */
		deleteNode = list->head;
		for(i = 0; i < index; i++)
		{
			deleteNode = deleteNode->next;
		}
	}

	if (deleteNode->last != NULL)
		deleteNode->last->next = deleteNode->next;
	if (deleteNode->next != NULL)
		deleteNode->next->last = deleteNode->last;
	if (list->tail == deleteNode)
		list->tail = deleteNode->last;
	if (list->head == deleteNode)
		list->head = deleteNode->next;
	free(deleteNode);	
	
	list->size--;

	return 1;
}


int bl_deleteNodeWithKey(bucketlist* list, int key)
{
	bucketlistnode * deleteNode = NULL;
	if (list == NULL || list->size == 0 || list->head == NULL)
		return 0;

	deleteNode = list->head;
	do
	{
		if (deleteNode->key == key)
		{	// delete this node and return
			if (deleteNode->last != NULL)
				deleteNode->last->next = deleteNode->next;
			if (deleteNode->next != NULL)
				deleteNode->next->last = deleteNode->last;
			if (list->tail == deleteNode)
				list->tail = deleteNode->last;
			if (list->head == deleteNode)
				list->head = deleteNode->next;
			free(deleteNode);
			list->size--;
			return 1;
		}
		deleteNode = deleteNode->next;
	} while (deleteNode != NULL);
	
	return 0;
}
