#ifndef dll
#define dll
#include"dll.h"

template <class Atype>
bool iter<Atype>::operator==(const iter<Atype> & rhs) const
{
	return ((this->pointAt == rhs.pointAt)?true:false);
}
template <class Atype>
bool const_iterator<Atype>::operator==( const const_iterator<Atype> & rhs) const
{
	return ((this->pointAt == rhs.pointAt)?true:false);
}
template <class Atype>
void List<Atype>::copy( List<Atype>& rhs)
{
	iter<Atype> i(begin());
	iter<Atype> j(rhs.begin());
	while(i!=end()&&(j!=rhs.end()))
			//so nodes are not created when already created
	{
		i->value= *j;
		i++;
		j++;
	}
	if (i==end())		//so lhs is shorter then rhs
		while(j!=rhs.end())
		{
			push_back(*j);
			j++;
		}
	else				//lhs is longer then rhs
		erase(i,end());
	return;
	//eraseAll();while (j!=end())insert(i,*rhs);
}
//end of iterator functions

template <class Atype>
const List<Atype>& List<Atype>::operator=( List<Atype>& rhs)
{
	copy(rhs);
}

template <class Atype>
unsigned int 	List<Atype>::size()
{
	int count=0;
	iter<Atype> i(begin());
	while(i!=end())
	{
		i++;
		count++;
	}
	return count;
}

template <class Atype>
bool List<Atype>::isEmpty() const
{
	return ((header.next==&header)?true:false);
}
template <class Atype>
const const_iterator<Atype> 	List<Atype>::cBegin() const
{
	const_iterator<Atype> j(header.next);
	return(j);
}
template <class Atype>
const const_iterator<Atype> 	List<Atype>::cEnd() const
{
	const_iterator<Atype> j(&header);
	return(j);
}

template <class Atype>
iter<Atype>			List<Atype>::begin()
{
	iter<Atype> j(header.next);
	return(j);
}

template <class Atype>
iter<Atype>			List<Atype>::end()
{
	iter<Atype> j(&header);
	return(j);
}

template <class Atype>
Atype & 		List<Atype>::front()
{
	if (isEmpty())
		throw(cerr<<"i am empty"<<endl);
	return header.next->value;
}
template <class Atype>
const Atype&	List<Atype>::front() const
{
	if (isEmpty())
		throw(cerr<<"i am empty"<<endl);
	return header.next->value;
}
template <class Atype>
Atype& 			List<Atype>::back()
{
	if (isEmpty())
		throw(cerr<<"i am empty"<<endl);
	return header->previous.value;
}
template <class Atype>
const Atype&	List<Atype>::back() const
{
	if (isEmpty())
		throw(cerr<<"i am empty"<<endl);
	return header->previous.value;
}
template <class Atype>
void			List<Atype>::push_front(const Atype& aValue)
{
	insert(begin(),aValue);
	return;
}
template <class Atype>
void			List<Atype>::pop_front()
{
	if (isEmpty())
		return;
	iter<Atype> i(begin());
	erase(i);
}
template <class Atype>
void			List<Atype>::push_back(const Atype& aValue)
{
	insert(end(),aValue);
}
template <class Atype>
void			List<Atype>::pop_back()
{
	if (isEmpty())
		return;
	iter<Atype> i(header.previous);
	erase(i);
}

template <class Atype>
iter<Atype> 		List<Atype>::insert(iter<Atype> i, const Atype &aValue)
{
	Node<Atype> * n=new Node<Atype>(*(i.getPointAt()->previous), aValue);
	iter<Atype> j(n);
	n=0;
	return j;
}


template <class Atype>
void 			List<Atype>::erase(iter<Atype> i)
{
	delete (i.getPointAt());
}

template <class Atype>
void			List<Atype>::erase(iter<Atype> i, iter<Atype> j)
{
	if (i==j)
		return;
	
	--j;
	while (i!=j)
	{
		erase(j--);//erase what j was j is decremented
	}
	erase (i);
}


template <class Atype>
void 			List<Atype>::splice(iter<Atype> where, List<Atype> & list)
{
	iter<Atype> lookAt(list.end());//should be looking at header
	where->previous->next=lookAt->next;
	lookAt->next->previous=where->previous;
	lookAt->previous->next= where.getPointAt();
	where->previous=lookAt->previous;
	lookAt->next=lookAt->previous= lookAt.getPointAt();
	//list should now be empty
}
//sort(List& rhs);

template <class Atype>
void List<Atype>::print(ostream& out) const
{	
	if (isEmpty())
	{
		out << endl;
		return;
	}
	//const_iterator<Atype> i(begin());
   iter<Atype>  i(begin());
	while(i != end())
	{
		out << i->value;
		out << " ";
		i++;
	}
	out << endl;
	return;
}

template <class Atype>
void List<Atype>::printAll(ostream& out) const
{
	//List<Atype>::const_iterator p(begin())
	//for(; p!=end();++p)
	//out<<p->value <<' ';
}


// node functions:

template <class Atype>
Node<Atype>::Node()//should only call for header
{
	previous = this;
	next = this;
}
template <class Atype>
Node<Atype>::Node(Node& ANode,const Atype& Avalue)
{
	Link(ANode);
	value = Avalue;
}
template <class Atype>
Node<Atype>::~Node()
{
	UnLink();
	next=previous=this;
}
template <class Atype>
void Node<Atype>::Link(Node& ANode)
		//putsin right after the place pointed at
{
	next=ANode.next;
	ANode.next=this;
	previous=next->previous;
	next->previous=this;
}

template <class Atype>
void Node<Atype>::UnLink()
{
	previous->next=next;
	next->previous=previous;
	next=previous=0;
}

/*

*/
#include "dll.cpp"
#endif
