/*********************************************************************
 * This file is part of the cpplibs suite.
 *
 * Copyright (C) 2001 Topi Mäenpää
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.4 $
 *********************************************************************/

#ifndef _EVENT_H
#define _EVENT_H

#include "List.h"

namespace util
{
	template <class T> class EventSource;

	/**
	 * An interface for classes that are going to listen events from an
	 * event source. An event can be of any type, and it is wise to
	 * write a custom event class for each event listener type to avoid
	 * confusion. If, for example, two event sources fire <i>int</i>
	 * events, then the listeners may be confused. Possible confusions
	 * can be solved by inspecting the source of the event, but this is
	 * not an elegant solution.
	 **/
	template <class T> class EventListener : virtual public Object
	{
	public:
		/**
		 * Called by EventSource whenever an event occurs. All registered
		 * listeners will be notified with the source attribute set to the
		 * source of the event.
		 * @param source the source of the event. Helps in avoiding possible
		 *               confusions with similar event types.
		 * @param event the event that was just fired
		 **/
		virtual void eventOccured(EventSource<T>& source, const T& event) = 0;
	};

	/**
	 * EventSource provides convenient means of adding, removing and
	 * notifying event listeners.
	 **/
	template <class T> class EventSource : virtual public Object
	{
	public:
		/**
		 * Add a new event listener. The new listener is added only if it
		 * is not in the listener list already. The listener will be
		 * notified whenever an event is fired.
		 * @param listener a pointer to a class that inherits EventListener
		 **/
		void addEventListener(EventListener<T>* listener);
		/**
		 * Remove an event listener. The removed listener will get no
		 * further notifications of the events happened.
		 * @param listener a pointer to a class that inherits EventListener
		 **/
		void removeEventListener(EventListener<T>* listener);

	protected:
		/**
		 * Notify all registered event listeners.
		 * @param event the event to fire
		 **/
		void fireEvent(const T& event);

		/**
		 * Notify all registered event listeners.
		 * @param event a pointer to the event to be fired. The event is
		 *              automatically deleted upon the exit of this method.
		 **/
		void fireEvent(const T* event);

	private:
		List<EventListener<T>* > _lstEventListeners;
	};

	template <class T> void EventSource<T>::addEventListener(EventListener<T>* listener)
	{
		if (!_lstEventListeners.contains(listener))
			_lstEventListeners += listener;
	}

	template <class T> void EventSource<T>::removeEventListener(EventListener<T>* listener)
	{
		_lstEventListeners -= listener;
	}
	
	template <class T> void EventSource<T>::fireEvent(const T& event)
	{
		for (int i=_lstEventListeners.getLength();i--;)
			_lstEventListeners[i]->eventOccured(*this, event);
	}

	template <class T> void EventSource<T>::fireEvent(const T* event)
	{
		for (int i=_lstEventListeners.getLength();i--;)
			_lstEventListeners[i]->eventOccured(*this, *event);
		delete event;
	}
}

#endif
