/*-------------------------------------------------------*/
/* ProjectOmega                 									*/
/* Written by T.Miles												*/
/* ID: 289175															*/
/* Module:	EventList Class									   */
/* Linked list storage class for midievents					*/
/* Used to be a template, but things went wrong!			*/
/*-------------------------------------------------------*/

#include "misc/eventlist.h"

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

// Listnode constructor
ListNode::ListNode(MidiEvent *item){
	listItem=item;	
	prev=NULL;
	next=NULL;
}

ListNode::~ListNode(){
	if (listItem)
		delete listItem;
}

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

// Linklist constructor - Initialise pointers etc
LinkList::LinkList(){
	head=NULL;//new LinkNode(NULL);	// Create one empty node
	tail=NULL;
	listsize=0;
}

// Destructor - Go through the list freeing memory
LinkList::~LinkList(){
	cout << "Deleting List" << endl;
	
	ListNode *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 results - for debug only
void LinkList::PrintList(){
	ListNode *current;
	current=head; // The first item is redundant!
	
	for (int n=0;n<500;n++){
		cout << current->listItem->me_absTime << endl;
		current=current->prev;
	}
}


// AddEvent - Adds an item to the list
void LinkList::AddItem(MidiEvent * item){
	ListNode *temp=new ListNode(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
// & set's the iterator to point at it
MidiEvent * LinkList::GetItem(UINT index){
	ListNode *current=tail;
	for (UINT n=0;n<index;n++){
		if (current!=NULL)
			current=current->prev;
	}
	if (current!=NULL){
		iter=current;
		return current->listItem;
	}
	else{
		iter=head;
		return NULL;
	}
}

// Updates the iterator to point to the next item
// then returns it's value
// Should be used in conjuction with GetItem()
MidiEvent *LinkList::GetNextItem(){
	if (iter->prev!=NULL){
		iter=iter->prev;
		return iter->listItem;
	}
	else
		return NULL;
}

void LinkList::ResetIterator(){
	iter=head;
}

MidiEvent *LinkList::GetCurrentItem(){
	if (iter!=NULL)
		return iter->listItem;
	else
		return NULL;
}

UINT LinkList::GetSize(){
	return listsize;
}

void LinkList::InsertItem(MidiEvent *item, UINT index){
	ListNode *newNode=new ListNode(item);
	ListNode *current=iter;
	
	BOOL end=FALSE;
			
	if (current==NULL){	// We've inserted to an empty list
		head=newNode;
		tail=newNode;
	}
	else{
		if (current->prev==NULL)
			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++;
}

void LinkList::DeleteItem(UINT index){
	ListNode *current=tail;

	if (index==0){					// We've deleted the first item
		if (tail->prev!=NULL)
			tail->prev->next=NULL;
			
		tail=tail->prev;

		if (current!=NULL)
			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;
			if (current!=NULL)
				delete current;
			listsize--;
		}
	}
}
