#include "collisiondetector.h"
#include "utils.h"
#include "messages.h"
#include <d3dx9mesh.h>

unsigned int CollisionDetector::SendMsg(Msg* RecievedMsg, Msg** SentMsgs)
{
	assert(TerrainObject!=NULL);

	int NumMessagesSent = 0;

	if(RecievedMsg->Type == mMove)
	{
		MoveMsg* Message = static_cast<MoveMsg*>(RecievedMsg);
		//First we will look at collisions with the terrain.
		//HACK:*** Right now, I am operating on the assumption that the terrain
		// squares are all 1 unit wide, which could change.
		//TODO:***Make this a LOT more efficient; right now, this function
		// probably checks every polygon in the mesh to see if it intersects, but we should
		// know which one it will intersect, if any already.  Anyway, this should work
		// for now.
		D3DXVECTOR3 ObjectPosition = static_cast<PhysicalEntity*>(Message->Sender)->GetGroundContactPoint();
		D3DXVECTOR3 Direction;
		D3DXVec3Normalize(&Direction, &Message->MovementAmount);
		BOOL HitFound;
		float Distance;
		DWORD FaceHit;
		D3DXIntersect(TerrainObject->GetTerrainMesh()->GetD3DXMesh(), &ObjectPosition, &Direction, &HitFound, &FaceHit,NULL,NULL, &Distance, NULL, NULL);
		
		if(HitFound&&Distance<D3DXVec3Length(&(Message->MovementAmount)))
		{
			//static int collisioncount = 0;
			//collisioncount++;
			//if(collisioncount>50)
			//{
			//	MessageBox(NULL, "test", NULL, NULL);
			//}

			//We only OK the move up to the distance where it hit, then we send a 
			// collision message along with the MoveOK message
			float RatioAllowed = Distance/D3DXVec3Length(&(Message->MovementAmount))-.1f;
			
			MoveOKMsg* Result = new MoveOKMsg;
			Result->MovementAmount = Message->MovementAmount*RatioAllowed;
			Result->Sender = this;
			Result->Reciever = Message->Sender;
			
			//TODO: This is currently a special collision message; perhaps
			// this should be a normal collision (to allow deformation of land)
			//All we need to do is compute the normal of the face that was collided with
			GroundCollisionMsg* CollisionMessage = new GroundCollisionMsg;
            CollisionMessage->Reciever = Message->Sender;
			CollisionMessage->Sender = this;
            CollisionMessage->Normal = 	TerrainObject->GetFaceNormal(FaceHit);		
			
			SentMsgs[0] = Result;
			SentMsgs[1] = CollisionMessage;
			NumMessagesSent = 2;
		}
		else
		{
			//If no hit was found, then send a MoveOK Message to the original sender
			// allowing it to move the full distance it requested
			MoveOKMsg* Result = new MoveOKMsg;
			Result->MovementAmount = Message->MovementAmount;
			Result->Sender = this;
			Result->Reciever = Message->Sender;

			SentMsgs[0] = Result;
			NumMessagesSent = 1;   						
		}
		//TODO: We will at some point want to deal with collisions b/t other
		// objects.
	}

	return NumMessagesSent;
}

void CollisionDetector::SetTerrainObject(Terrain* NewTerrain)
{
	TerrainObject = NewTerrain;
}

void CollisionDetector::AddObject(Entity* NewObject)
{
	ObjectList.MoveToHead();
	ObjectList.InsertAfter(NewObject);
}