#ifndef H_CORAL_LIST
#define H_CORAL_LIST
// This file is part of the Coral project.
// Please read the copyright notice in the LICENSE file.

#ifndef SWIG

#include <coral/coral.h>
#include "noncopy.h"

struct ListPtr;

struct EXPORT_coral List_Base {
private:
	friend struct ListPtr;
	friend struct List;
	struct List_Base* next;
	struct List_Base* prev;
public:
	List_Base() throw () : next(this), prev(this) {
		;
	}
	List_Base* getNext() throw () { return this->next; }
	List_Base* getPrev() throw () { return this->prev; }
	const List_Base* getNext() const throw () { return this->next; }
	const List_Base* getPrev() const throw () { return this->prev; }
	List_Base(struct List_Base* add_to_this) throw () {
		struct List_Base* n;
		n = add_to_this->next;
		this->next = n;
		this->prev = add_to_this;
		n->prev = this;
		add_to_this->next = this;
	}
	~List_Base() throw () { this->drop(); }
	void drop() throw () {
		struct List_Base* n = this->next;
		struct List_Base* p = this->prev;
		n->prev = p;
		p->next = n;
		this->next = this;
		this->prev = this;
	}
	bool isEmpty() const throw () {
		return this == this->next;
	}
	/** Add elem (which must be detached) to this. */
	void add(struct List_Base* elem) throw () {
		coral_assert(elem->isEmpty());
		struct List_Base* n = this->next;
		this->next = elem;
		elem->prev = this;
		n->prev = elem;
		elem->next = n;
	}
	/** Add behind */
	void add_back(struct List_Base* elem) throw () {
		coral_assert(elem->isEmpty());
		struct List_Base* p = this->prev;
		this->prev = elem;
		elem->next = this;
		p->next = elem;
		elem->prev = p;
	}
	/** Move elem (which can be on another list) to this. */
	void move(struct List_Base* elem) throw () {
		elem->drop();
		this->add(elem);
	}

	/* NOTE this is a linear operation! */
	int size() const {
		int thesize = 0;
		const struct List_Base* h = this->next;
		while (h != this) {
			++thesize;
			h = h->next;
		}
		return thesize;
	}


};


struct EXPORT_coral ListPtr {
private:
	struct List_Base* cur;
public:
	ListPtr(List_Base* l) : cur(l) { ; }
	~ListPtr() throw () { ; }

	bool operator==(const ListPtr& e) const {
		return this->cur == e.cur;
	}
	bool operator!=(const ListPtr& e) const {
		return this->cur != e.cur;
	}
	struct List_Base* operator*() throw () { return this->cur; }

#ifndef SWIG
	struct ListPtr& operator++() throw () { this->cur = this->cur->next; return *this; }
	struct ListPtr operator++(int) throw () { ListPtr t = *this; this->cur = this->cur->next; return t; }
	struct ListPtr& operator--() { this->cur = this->cur->prev; return *this; }
	struct ListPtr operator--(int) throw () { ListPtr t = *this; this->cur = this->cur->prev; return t; }

#endif


};


struct EXPORT_coral List : public List_Base {
public:
	List() : List_Base() { ; }
	List(List* l) : List_Base(l) { ; }
	typedef struct ListPtr iterator;
	struct ListPtr begin() throw () { return ListPtr(this->next); }
	struct ListPtr end() throw () { return ListPtr(this); }

};

#endif

#endif

