/// @file factory.hh
/// @author Stefan Schmitt <sschmitt@ee.uwa.edu.au>
/// @version 1.0
/// @date 2003-07
/// 
/// Declares Factory and Updater classes.

#ifndef FACTORY_HH
#define FACTORY_HH

#include "base/base.hh"
#include "base/templates.hh"

namespace EyeMind {

class Updater; // forward declaration



/// Manufacturing and book-keeping of objects.
/// Objects can be created using the () operator. The Factory class
/// keeps book of all created objects and destroys them in the destructor, i.e
/// all objects live as long as their Factory object. The object are destroyed
/// in reverse order as they have been created.

template <typename T>
class Factory : public Updatable
{
private:
	/// Linked list type.
	struct LList {
		T* entity;
		LList* next;
	};

	LList* instances; ///< Pointer to last element in linked list.
	Updater* updater; ///< Pointer to assigned Updater object.

	NO_COPYING(Factory); ///< Prevent copying.

public:
	/// Default constructor; initializes data members.
	Factory();

	/// Constructor; registers new Factory with Updater u.
	Factory(Updater& u);

	/// Destructor; destroys all objects created using () and unregister
	/// with updater.
	virtual ~Factory();

	/// Tells all created object to update (if applicable).
	virtual bool Update();

	/// Returns a reference to a newly created instance of T.
	T& operator()(void);
};


template <typename T>
Factory<T>::Factory()
{
	instances = NULL;
	updater = NULL;
}


template <typename T>
Factory<T>::Factory(Updater& u) : Factory()
{
	updater = &u;
	u.Register(*this);
}


template <typename T>
Factory<T>::~Factory()
{
	if (updater)
		updater->Unregister(*this);


	LList *i,*in;

	// iterate through linked list, destroying list elements and
	// created objects.
	i=instances;
	while (i) {
		in=i->next;
		delete i->entity;
		delete i;
		i=in;
	};


}


template <typename T>
bool Factory<T>::Update()
{
	if (!instances)
		return false;

	// check if the Factory products can be updated
	if (!dynamic_cast<Updatable*>(instances->entity))
		return false;

	LList* i = instances;
	while (i) {
		// This cast is 100% safe because the legality of this cast
		// was tested some lines above.
		reinterpret_cast<Updatable*>(i->entity)->Update();
		i=i->next;
	};

	return true;
}
	

template <typename T>
T& Factory<T>::operator()(void)
{
	// create new instance
	T* temp=new T;
	// create new list item
	LList* first=new LList;
	
	// prepend new list item
	first->entity=temp;
	first->next=instances;
	instances=first;
	
	return *temp;
}



/// Provides a container/handle for Updatable objects. All objects that are
/// registered with the Updater are updated when Updater::Update() is called.

class Updater : public Updatable
{
private:
	LinkedList<Updatable> instances; ///< Updatable objects list.
	
	NO_COPYING(Updater); ///< Prevent copying.

public:
	/// Default constructor.
	Updater(){}

	/// Updates all registered objects; returns always \c true.
	virtual bool Update();

	/// Registers a new object to be updated by Updater.
	void Register(Updatable& u);
	
	/// Unregisters an object that should not updated anymore by Updater.
	void Unregister(Updatable& u);
};


}; // namespace EyeMind

#endif // FACTORY_HH
