#ifndef LIST_H
#define LIST_H

#include <iostream.h>
#include <assert.h>
#include "listnd.h"

// You know this class
// -------------------------------------------------------------------------

template <class NODETYPE>
class List {
	public:
		List();
		void insertAtFront(const NODETYPE &);
	        void insertAtBack(const NODETYPE &);
		bool isEmpty() const;
		void print() const;
	
	protected:
		ListNode<NODETYPE> *firstPtr;
		ListNode<NODETYPE> *lastPtr;
		ListNode<NODETYPE> *getNewNode(const NODETYPE &);
};
template <class NODETYPE>
List <NODETYPE>::List():firstPtr(0),lastPtr(0){}

template<class NODETYPE>
void List<NODETYPE>::insertAtFront(const NODETYPE &value)
{
	ListNode<NODETYPE> * newPtr=getNewNode(value);
	if (isEmpty())
		firstPtr=lastPtr=newPtr;
	else
	{
		newPtr->nextPtr=firstPtr;
		firstPtr=newPtr;
	}
}

template<class NODETYPE>
void List<NODETYPE>::insertAtBack(const NODETYPE &value)
{
	
	ListNode<NODETYPE> * newPtr=getNewNode(value);
	if (isEmpty())
		firstPtr=lastPtr=newPtr;
	else
	{
		lastPtr->nextPtr=newPtr;
		lastPtr=newPtr;
	}
}	

template <class NODETYPE>
bool List<NODETYPE>::isEmpty() const
{return firstPtr==0;}

template <class NODETYPE>
ListNode<NODETYPE> *List<NODETYPE>::getNewNode( const NODETYPE &value)
{
	ListNode<NODETYPE> *ptr= new ListNode<NODETYPE>(value);
	assert(ptr!=0);
	return ptr;
}

template <class NODETYPE>
void List<NODETYPE>::print () const
{
	if (isEmpty()) {
		cout<<"The list is empty\n\n";
		return;
	}

	ListNode<NODETYPE> *currentPtr=firstPtr;
	
	while(currentPtr!=0){
		currentPtr->data.print();
		currentPtr=currentPtr->nextPtr;
	}
	
	cout<<"\n\n";
}
#endif

