/**
 * \file List.h
 * \date 26.10.2002
 * \author Matus Horvath
 *
 * Generic list class
 */


#ifndef LIST_H
#define LIST_H

#include <stdlib.h>

template<class TYPE>
class List
{
public:
	class Element;

private:
	Element* first;
	Element* last;
	
	int count;
	
protected:

public:
	inline List();
	~List();
	
	void FromList(List<TYPE>* list);

	int GetCount() { return count; }
	
	void Add(TYPE* data);
	
	inline bool Remove(TYPE* data);
	bool RemoveElement(Element* elem);

	Element* Find(TYPE* data);

	void Clear();
	
	Element* GetFirst() { return first; }
	Element* GetLast() { return last; }
	Element* GetNext(Element* elem) { return elem->next; }
	Element* GetPrev(Element* elem) { return elem->prev; }

public:
	class Element
	{
	public:
		TYPE* data;
	
		Element* prev;
		Element* next;
	};

};

#define LIST_FOR_EACH(type, name, list) \
	for(List<type >::Element* (name) = (list).GetFirst(); \
		(name) != NULL; \
		(name) = (list).GetNext(name))


template<class TYPE>
List<TYPE>::List()
	: first(NULL), last(NULL), count(0)
{
}

template<class TYPE>
void List<TYPE>::FromList(List<TYPE>* list)
{
	first = list->first;
	last = list->last; 
	count = list->count;

	list->first = NULL;
	list->last = NULL;
	list->count = 0;
}

template<class TYPE>
void List<TYPE>::Add(TYPE* data)
{
	Element* elem = new Element;
	elem->data = data;
	
	if(last == NULL)
	{
		first = last = elem;
		elem->next = elem->prev = NULL;
	}
	else
	{
		last->next = elem;
		elem->prev = last;
		elem->next = NULL;
		last = elem;
	}
	
	count++;
}

template<class TYPE>
bool List<TYPE>::Remove(TYPE* data)
{
	return RemoveElement(Find(data));
}

template<class TYPE>
bool List<TYPE>::RemoveElement(Element* elem)
{
	if(elem == NULL) return false;
	
	if(elem->prev == NULL) first = elem->next;
	else elem->prev->next = elem->next;
	if(elem->next == NULL) last = elem->prev;
	else elem->next->prev = elem->prev;

	if(elem->data != NULL) delete elem->data;
	delete elem;
	
	count--;
	
	return true;
}

//template<class TYPE>
//List<TYPE>::Element* List<TYPE>::Find(TYPE* data)
//{
//	List<TYPE>::Element* elem = first;
//	
//	while(elem != NULL)
//	{
//		if(elem->data == data) return elem;
//		elem = elem->next;
//	}
//	
//	return NULL;
//}

template<class TYPE>
void List<TYPE>::Clear()
{
	Element* elem;
	
	while(first != NULL)
	{
		delete first->data;
		
		elem = first->next;
		delete first;
		first = elem;
	}
	
	count = 0;
}

template<class TYPE>
List<TYPE>::~List()
{
	Clear();
}


#endif // LIST_H
