/* 
 *  Ths code in this file is part of tcptrack. For more information see
 *    http://www.rhythm.cx/~steve/devel/tcptrack
 *
 *     Copyright (C) Steve Benson - 2003
 *
 *  tcptrack is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your
 *  option) any later version.
 *   
 *  tcptrack is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  
 */

/*
 * This whole thing is a basic linked list. it will eventually be replaced
 * by the stl lists class.
 *
 */

#ifndef LIST_H
#define LIST_H 1

#include <stdio.h>
#include <iostream>

template<class T> class ListIterator;

template<class T> class ListNode
{
public:
	ListNode();
	ListNode( T newItem );
	
	T getItem();
	void setItem( T newItem );
	
	void setNext( ListNode<T> *n );
	ListNode<T> *getNext();
private:
	T item;
	ListNode<T> *next;	
};

template<class T> class List
{
public:
	List();
	List(List<T> *orig);
	List(const List<T> &orig);
	~List();
	void append( T newItem );
	ListIterator<T> getIterator();
	bool isEmpty();
	bool remove( T item );
private:
	ListNode<T> *head;
	ListNode<T> *tail;
	bool isEmptyFlag;
};



template<class T> bool List<T>::isEmpty()
{
	return isEmptyFlag;
}

template<class T> ListIterator<T> List<T>::getIterator()
{
	ListIterator<T> li;
	li.setCurrent(head);
	return li;
}

template<class T> bool List<T>::remove( T item )
{
	if( isEmpty() )
		return false;

	ListNode<T> *prev = NULL;

	for( ListNode<T> *nodeToRemove = head; nodeToRemove; )
	{
		if( nodeToRemove->getItem() == item )
		{
			if( head == nodeToRemove ) // removing the head node
			{
				head=nodeToRemove->getNext();
				delete nodeToRemove;
				if( head == NULL )
					isEmptyFlag=true;
			}
			else
			{
				prev->setNext( nodeToRemove->getNext() );				
				if( nodeToRemove == tail )
					tail=prev;
				delete nodeToRemove;
			}
			return true;
		}
		// set nodeToRemove to the next node
		prev = nodeToRemove;
		nodeToRemove = nodeToRemove->getNext();
	}
	return false;
}
	

template<class T> void List<T>::append( T newItem )
{
	//isEmptyFlag = false;
	//if( head == NULL )
	if( isEmptyFlag )
		head = tail = new ListNode<T>(newItem);
	else
	{
		ListNode<T> *newTail = new ListNode<T>(newItem);
		tail->setNext(newTail);
		tail=newTail;
	}
	isEmptyFlag=false;
}

template<class T> List<T>::List()
{
	head=tail=NULL;
	isEmptyFlag=true;
}


template<class T> List<T>::List(List<T> *orig)
{
	head=tail=NULL;
	isEmptyFlag=true;
		
	if( orig->head != NULL )
		for( ListNode<T> *ln = orig->head; ln; ln = ln->getNext() )
			this->append(ln->getItem());

}

template<class T> List<T>::List(const List<T> &orig)
{
	head=tail=NULL;
	isEmptyFlag=true;
	
	if( orig.head != NULL )
		for( ListNode<T> *ln = orig.head; ln; ln = ln->getNext() )
			this->append(ln->getItem());
}


template<class T> List<T>::~List()
{
	for(ListNode<T> *i=head;i;)
	{
		ListNode<T> *next = i->getNext();
		delete i;
		i=next;
	}
}



template<class T> ListNode<T>::ListNode()
{
	item = NULL;
	next = NULL;
}

template<class T> ListNode<T>::ListNode( T newItem )
{
	item = newItem;
	next = NULL;
}

template<class T> T ListNode<T>::getItem()
{
	return item;
}

template<class T> void ListNode<T>::setItem( T newItem )
{
	item = newItem;
}

template<class T> ListNode<T> *ListNode<T>::getNext()
{
	return next;
}

template<class T> void ListNode<T>::setNext( ListNode<T> *n )
{
	next = n;
}

#endif

