#include "messages.h"

MessageManager::MessageManager()
{
	//Allocate the listeners array of linked list
    Listeners = new LList<Entity*>[mTotal];
}

MessageManager::~MessageManager()
{
	//We only delete the array... the values inside the array
	// should have been dealt with elsewhere
	delete []Listeners;
}

void MessageManager::QueueMessages(Msg** NewMessages, int NumNewMessages)
{
	//reversing the order here isn't really necessary; I am doing it b/c
	// that way messages will be sent in the order they are sent to
	// this object... it just feels more right that way.
	for(int i=NumNewMessages-1;i>=0;i--)
	{
		MessagesWaiting.Push(NewMessages[i]);
	}
}

void MessageManager::AddListener(MessageType ListenerMessage, Entity* NewListener)
{
	//it shouldn't matter where we insert it... we don't care about order
	Listeners[ListenerMessage].InsertAfter(NewListener);
}

void MessageManager::ProcessAllMessages()
{
	//Ok.. this is where all the important work is done.
	//We keep going until there are no messages left.
	Msg* NewMessages[MAXMESSAGES];
	int NumNewMessages;
	while(!MessagesWaiting.IsEmpty())
	{
		Msg* NextMessage;
        //Pop the first message from the stack
		NextMessage = MessagesWaiting.Pop();

        //send it to the target that it specified (if any)
		if(NextMessage->Reciever!=NULL)
		{
			NumNewMessages = NextMessage->Reciever->SendMsg(NextMessage, NewMessages);
			//add any resulting messages back to the stack
			QueueMessages(NewMessages, NumNewMessages);
		}
		
		//now send it to any listeners for that message
		Listeners[NextMessage->Type].MoveToHead();
		Listeners[NextMessage->Type].Next();
		while(!Listeners[NextMessage->Type].AtEnd())
		{
			NumNewMessages = Listeners[NextMessage->Type].GetCurrent()->Data->SendMsg(NextMessage, NewMessages);
			//add any resulting messages back to the stack
			QueueMessages(NewMessages, NumNewMessages);
			Listeners[NextMessage->Type].Next();
		}
	
		//finally, this is a special case that could be improved later
		//TODO: is there a better way to handle this message?
		if(NextMessage->Type==mNewEntity)
		{
			//We add the new entity to somewher in the list 
            EntityList->InsertAfter(static_cast<NewEntityMsg*>(NextMessage)->NewEntity);
		}

        //free the memory associated with the message; it's done now
		delete NextMessage;
	}
}

void MessageManager::SetEntityList(LList<Entity*>* NewEntityList)
{
	EntityList = NewEntityList;
}
