/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
****************************************************************************/

#pragma once

#include "glmCoreAPI.h"
#include "glmMemory.h"

namespace glm
{
	/**
	* \brief Base class of all event objects
	*
	* All events derive from this class, which is responsible for knowing the source object of the event.
	*
	* Example :
	*
	\code
	class Producer ;

	// MyEvent
	class MyEvent : public Event< Producer >
	{
	public:

	MyEvent( const Producer& source ) 
	: 
	Event< Producer >( source )
	{
	}
	} ;

	// IMyEventListener
	class IMyEventListener 
	{
	public:

	virtual void onMyEvent( const MyEvent& event ) = 0 ;
	} ;

	// Producer
	class Producer
	{
	public:

	Producer() 
	:
	_myEventSource( &IMyEventListener::onMyEvent )
	{
	}

	void foo() 
	{ 
	_myEventSource.publishEvent( MyEvent( *this ) ) ;
	}


	void addMyEventListener( IMyEventListener& listener ) 
	{ 
	_myEventSource.addListener( listener ) ; 
	}

	void removeMyEventListener( IMyEventListener& listener ) 
	{ 
	_myEventSource.removeListener( listener ) ; 
	}

	private:

	EventSource< IMyEventListener, MyEvent > _myEventSource ;
	} ;

	// Consumer
	class Consumer : public IMyEventListener
	{
	public:

	virtual ~Consumer() 
	{
	}

	protected:

	void onMyEvent( const MyEvent& event )
	{
	//do stuff
	}
	} ;
	\endcode
	*
	* \ingroup events
	* \author Golaem <dev@golaem.com>
	*/
	template < class TSource>
	class Event
	{
	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::GolaemShared)

		/**
		* \brief constructor
		* \param source of the event (usually this)
		*/
		Event( const TSource& source ) ;

		/**
		* \brief destructor
		*/
		virtual ~Event() ;

		/**
		* \brief accessor to the emitter
		* \return a const reference to the source of the event
		*/
		const TSource& getSource() const ;

	private:

		/// event emitter
		const TSource* source_ ;
	};

	//-------------------------------------------------------------------------
	// constructor
	//-------------------------------------------------------------------------
	template < class TSource >
	Event< TSource >::Event( const TSource& source )
		:
	source_( &source )
	{
	}

	//-------------------------------------------------------------------------
	// destructor
	//-------------------------------------------------------------------------
	template < class TSource >
	Event< TSource >::~Event()
	{
	}

	//-------------------------------------------------------------------------
	// getSource
	//-------------------------------------------------------------------------
	template < class TSource >
	inline const TSource&
		Event< TSource >::getSource() const
	{
		return *source_ ;
	}
}

