#include "EventManager.h"

#include "HashString.h"

#include "SDL.h"
#include "DebugUtil.h"

template<> EventManager* TSingleton<EventManager>::m_pInstance = NULL;

EventManager::EventManager()
{

}

EventManager::~EventManager()
{
	for(size_t i = 0; i < m_vEventListenerSets.size(); i++)
		delete m_vEventListenerSets[i];
	m_vEventListenerSets.clear();


	while(m_qEventQueue.size() > 0)
	{
		delete m_qEventQueue.front();
		m_qEventQueue.pop();
	}
}

void EventManager::ProcessQueue(unsigned int totalTime /* = 0 */)
{
	Uint32 startTime = SDL_GetTicks();
	Uint32 lastProcessingTime = 0;

	while(lastProcessingTime - startTime < totalTime || totalTime == 0)
	{
		if(m_qEventQueue.size() == 0)
			return;

		IEvent* pEvent = m_qEventQueue.front();
		m_qEventQueue.pop();

		HashString eventType = pEvent->GetEventType();
		EventListenerSet* pSet = GetListenerSet(eventType);

		if(pSet)
		{
			std::vector<IEventListener*>::iterator listenerIt = pSet->EventListeners.begin();
			while(listenerIt != pSet->EventListeners.end())
			{
				if((*listenerIt)->HandleEvent(pEvent)) //If it returns true it has consumed the event
					break;

				listenerIt++;
			}
		}

		delete pEvent;
		lastProcessingTime = SDL_GetTicks();
	}
}

void EventManager::AddEventListener(const HashString &eventType, IEventListener *pListener)
{
	EventListenerSet* pSet = GetListenerSet(eventType);
	if(!pSet)
	{
		pSet = new EventListenerSet();
		pSet->EventType = eventType;
		m_vEventListenerSets.push_back(pSet);
	}

	for(unsigned int i = 0; i < pSet->EventListeners.size(); i++)
	{
		if(pSet->EventListeners[i] == pListener)
			return; //Listener already in list.
	}

	pSet->EventListeners.push_back(pListener);
}

void EventManager::RemoveEventListener(const HashString &eventType, IEventListener *pListener)
{
	EventListenerSet* pSet = GetListenerSet(eventType);
	if(!pSet)
		return; //throw error

	std::vector<IEventListener*>::iterator it = pSet->EventListeners.begin();
	while(it != pSet->EventListeners.end())
	{
		if((*it) == pListener)
		{
			pSet->EventListeners.erase(it);
			return;
		}
		
		it++;
	}
}

void EventManager::RemoveEventListenerFromAll(IEventListener *pListener)
{
	std::vector<EventListenerSet*>::iterator setIter = m_vEventListenerSets.begin();
	while(setIter != m_vEventListenerSets.end())
	{
		std::vector<IEventListener*>::iterator it = (*setIter)->EventListeners.begin();
		while(it != (*setIter)->EventListeners.end())
		{
			if((*it) == pListener)
			{
				(*setIter)->EventListeners.erase(it);
				break;
			}

			it++;
		}

		setIter++;
	}
}

void EventManager::TriggerEvent(IEvent *pEvent)
{
	DebugUtil::outputDebugText("Event received\n");
	//HashString eventType = pEvent->GetEventType();
	DebugUtil::outputDebugText("Event received: %s\n", pEvent->GetEventType().getStr().c_str());
	EventListenerSet* pSet = GetListenerSet(pEvent->GetEventType());

	if(!pSet)
		return; //Throw low priority error

	std::vector<IEventListener*>::iterator listenerIt = pSet->EventListeners.begin();
	while(listenerIt != pSet->EventListeners.end())
	{
		if((*listenerIt)->HandleEvent(pEvent)) //If it returns true it has consumed the event
			return;

		listenerIt++;
	}

	delete pEvent;
}

void EventManager::QueueEvent(IEvent *pEvent)
{
	if(GetListenerSet(pEvent->GetEventType()))
		m_qEventQueue.push(pEvent);
// 	else
// 		throw ERROR;
}

EventManager::EventListenerSet* EventManager::GetListenerSet(const HashString &eventType)
{
	std::vector<EventListenerSet*>::iterator it = m_vEventListenerSets.begin();
	while(it != m_vEventListenerSets.end())
	{
		if((*it)->EventType == eventType)
			return (*it);

		it++;
	}

	return 0;
}
