#ifndef _MYLLIST
#define _MYLLIST

#include <assert.h>

template <class ObjectType> class Node
{
public:
	Node* Prev;
	Node* Next;
	ObjectType Data;
};

template <class ObjectType> class LList
{
public:
	LList()
	{
		HeadTail = new Node<ObjectType>;
		HeadTail->Next = HeadTail;
		HeadTail->Prev = HeadTail;
		Current = HeadTail;
	}

	~LList()
	{
		Node<ObjectType>* Temp;
		HeadTail->Prev->Next = NULL;
		Current = HeadTail;
		while(Current!=NULL)
		{
			Temp = Current->Next;
			delete Current;
			Current = Temp;
		}
	}

	//Inserts a new node after the current node and returns a pointer to the new node
	//The current node is set to the new node
	Node<ObjectType>* InsertAfter(ObjectType Data)
	{
		Node<ObjectType>* Temp = new Node<ObjectType>;
		Temp->Data = Data;
		Temp->Next = Current->Next;
		Temp->Prev = Current;
		Current->Next->Prev = Temp;
		Current->Next = Temp;
		return Temp;
	}

	//Inserts new node before the current node
	Node<ObjectType>* InsertBefore(ObjectType Data)
	{
		Node<ObjectType>* Temp = new Node<ObjectType>;
		Temp->Data = Data;
		Temp->Next = Current;
		Temp->Prev = Current->Prev;
		Current->Prev->Next = Temp;
		Current->Prev = Temp;
		return Temp;
	}

	//Moves current node to the previous node in the list
	// Returns NULL when the beginning of the list is reached;
	// otherwise it returns the new current node
	void Previous()
	{
		Current = Current->Prev;
	}

	//Moves current node to the next in the list
	// NOTE: User must check to see if node is still in list (not the end node)
	void Next()
	{
		Current = Current->Next;
	}

	//Returns the current node; Is invalid until a node is added
	Node<ObjectType>* GetCurrent()
	{
		return Current;
	}

	///NOTE:This function could EASILY break, if the node specified is not in this list
	// It only exists to make some functions more efficient
	void SetCurrent(Node<ObjectType>* NewCurrent)
	{
		Current = NewCurrent;
	}

	//Deletes the current node, unless the current node is the head
	//Move the current node to the one immediately after it in the list
	void DeleteCurrent()
	{
		if(Current==HeadTail)
		{
			return;
		}
		else
		{
			Node<ObjectType>* Temp = Current->Next;
			Current->Next->Prev = Current->Prev;
			Current->Prev->Next = Current->Next;
			delete Current;
			Current = Temp;
		}
	}

	void MoveToHead()
	{
		assert(HeadTail!=NULL);
		assert(Current!=NULL);
		Current = HeadTail;
	}


	bool AtEnd()
	{
		return (Current==HeadTail);
	}	

	bool AtHead()
	{
		return (Current==HeadTail);
	}	

	//This allows the user to set the data in the HeadTail node as a sentinel
	void SetSentinel(ObjectType SentinelData)
	{
		HeadTail->Data = SentinelData;
	}

	const int CountEntries()
	{
		int count = 0;
		Node<ObjectType>* Temp;
		Temp = HeadTail->Next;
		while(Temp!=HeadTail)
		{
			count++;
			Temp = Temp->Next;
		}
		return count;
	}

private:
	Node<ObjectType>* HeadTail;
	Node<ObjectType>* Current;
};

#endif