/* So help me if I don't have to reinvent the wheel!! */
/* No STL in StormC - it's a sin!           				*/

#ifndef _MYLIST_H
#define _MYLIST_H

//#include "defines.h"
#include "stormc:projects/omega/misc/systemdefs.h"
//#include "listnode.h"

#include <iostream.h>

template <class T>
class ListNode {
friend class LinkList<L>;
private:
	T listItem;
	ListNode *prev;
	ListNode *next;
	ListNode();
public:
	ListNode(T);
	~ListNode();
};

template <class L>
class LinkList{
private:
	ListNode<L> *head;
	ListNode<L> *tail;
	UINT listsize;
public:
	LinkList();
	~LinkList();
	void AddItem(L);
	void InsertItem(L, UINT);
	void DeleteItem(UINT);
	L GetItem(UINT);
	UINT GetSize();
	void PrintList();
};


/**************************************/
/* ListNode - Used by the linkedlist  */
/**************************************/

// Listnode constructor
template <class T>
ListNode<T>::ListNode(T item){
	listItem=item;
	prev=NULL;
	next=NULL;
}

template <class T>
ListNode<T>::~ListNode(){
//	delete p_listItem;
}

/**************************************/
/* LinkedList Template Class          */
/**************************************/

// Linklist constructor - Initialise pointers etc
template <class L>
LinkList<L>::LinkList(){
	head=NULL;//new ListNode<L>(NULL);	// Create one empty node
	tail=NULL;
	listsize=0;
}

// Destructor - Go through the list freeing memory
template <class L>
LinkList<L>::~LinkList(){
	ListNode<L> *current;
	UINT items=0;
	
	if (head==NULL)  // If we've got nothing to delete!
		return;
	
	current=head->next;
	if (current==NULL){	// Only 1 item to delete
		delete head;
		items++;
	}
	else
	while(current!=NULL){
		items++;
		delete current->prev;
		if (current->next==NULL){
			delete current;
			items++;
			current=NULL;
		}
		else
			current=current->next;
	}
	cout << items << " list items destroyed" << endl;

}

// PrintList - Go through the list showing resuLs - for debug only
template <class L>
void LinkList<L>::PrintList(){
	ListNode<L> *current;
	current=tail; // The first item is redundant!
	
	for (int n=0;n<listsize;n++){
//		cout << current->listItem << endl;
		current=current->prev;
	}
}
	
// AddEvent - Adds an item to the list
template <class L>
void LinkList<L>::AddItem(L item){
	ListNode<L> *temp=new ListNode<L>(item);
	
	if (listsize==0){		// Create our first node!
		head=temp;
		tail=temp;
	}
	else{
		temp->next=head;
		if (head!=NULL){
			head->prev=temp;
			head=temp;
		}
	}
	listsize++;
}

// Returns the n'th item of the list
template <class L>
L LinkList<L>::GetItem(UINT index){
	ListNode<L> *current=tail;
	for (UINT n=0;n<index;n++){
		if (current!=NULL)
			current=current->prev;
	}
	if (current!=NULL)
		return current->listItem;
	else
		return NULL;
}

template <class L>
UINT LinkList<L>::GetSize(){
	return listsize;
}

template <class L>
void LinkList<L>::InsertItem(L item, UINT index){
	ListNode<L> *newNode=new ListNode<L>(item);
	ListNode<L>	*current=tail;
	BOOL end=FALSE;
	
	if (current==NULL){	// We've inserted to an empty list
		head=newNode;
		tail=newNode;
	}
	else{	
		for (UINT n=0;n<index;n++){
			if (current->prev!=NULL)
				current=current->prev;
			else
				end=TRUE;
		}
		if (!end){
			if (current->next!=NULL){ 	// Insert in the middle
				current->next->prev=newNode;
				newNode->next=current->next;
				current->next=newNode;
				newNode->prev=current;
			}
			else
			if (current->next==NULL){		// Inserted at the beginning
				current->next=newNode;
				newNode->prev=current;
				tail=newNode;
			}
		}
		else
		if (current->prev==NULL){  // Inserted at the end
			current->prev=newNode;
			newNode->next=current;
			head=newNode;
		}
	}
	listsize++;
}

template <class L>
void LinkList<L>::DeleteItem(UINT index){
	ListNode<L> *current=tail;

	if (index==0){					// We've deleted the first item
		tail->prev->next=NULL;
		tail=tail->prev;
		delete current;
		listsize--;
		return;
	}	
	
	if (current!=NULL){
		for (UINT n=0;n<index;n++){
			if (current!=NULL)
				current=current->prev;
		}
		if (current!=NULL){	//	We haven't overshot!
			if (current->prev!=NULL)
				current->prev->next=current->next;
			if (current->next!=NULL)
				current->next->prev=current->prev;
			delete current;
			listsize--;
		}
	}
}
#endif