#ifndef MESSAGES_H
#define MESSAGES_H

#include "entity.h"
#include <d3dx8.h>
#include "llist.h"
#include "stack.h"

enum MessageType{mGroundCollision, mMove, mMoveOK, mTotal}; //Total is put in so we have a value to look at
											//to see the total number of message types

class Entity;
class PhysicalEntity;

//This define is so that we can limit how many messages can be returned from a
// get message function call, so we don't have to worry about overrunning
// array bounds.  We could do this dynamically, but this is much more efficient
#define MAXMESSAGES 50

class Msg
{
public:
	Entity* Sender;
	Entity* Reciever;
	MessageType Type;
	//Subclass this for every message type and add message specific data
};

class MessageManager
{
public:
	MessageManager();
	~MessageManager();

	//Adds another message to the list of messages to be processed
	void QueueMessages(Msg** NewMessages, int NumNewMessages);

	//Note that I am making this function responsible for freeing the message
	// memory... the mem is allocated by the sender and freed here.
	void ProcessAllMessages();
	void AddListener(MessageType ListenerMessage, Entity* NewListener);

private:
	//We need to store a list of all the listeners, indexed by message type
	//It will be stored as an array of linked lists
	LList<Entity*>* Listeners;
	//Here's where we store all of the messages that have been queued up..
	// actually, the QueueMessages function name is deceptive, b/c we actually
	// store it as a stack.  I had a damn good reason for doing it like this, but
	// I forget at the moment... It somehow solved a problem with a case of infinite 
	// message passing
	Stack<Msg*> MessagesWaiting;
};

class GroundCollisionMsg : public Msg
{
public:
	GroundCollisionMsg() {Type = mGroundCollision;}
	D3DXVECTOR3 Normal; //The normal of the surface that was collided with  
};

class MoveMsg : public Msg
{
public:
	MoveMsg() {Type = mMove;}

	//We are overriding this variable b/c the object must be a
	// physicalentity to send this message
	//PhysicalEntity* Sender;

	//We need to know where the thing is trying to move; This vector shows what
	// its change in position wants to be
	D3DXVECTOR3 MovementAmount;
};

class MoveOKMsg : public Msg
{
public:
	MoveOKMsg() {Type = mMoveOK;}

	//We are overriding this variable b/c the object must be a
	// physicalentity to recieve
	//PhysicalEntity* Reciever;

	//Here we tell the object how much it is ok to move; this may be less than it originally
	// requested if a collision occurred.
	D3DXVECTOR3 MovementAmount;
};

#endif