/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function Name: CheckCorkableAABB()
// Purpose: Check for collision	and react appropriately
// Original Author: Rueben Massey
// Creation Date: 6/13/2012
// Last Modification By: 
// Last Modification Date: 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CComponent_IntakePipeCollision::CheckCorkableAABB( float fDT )
{
	// create a return vector to hold all the objects the kd tree returns
	std::vector <CSceneObject*> NearestObjects;
	// create a unsigned int that will tell the kd tree what you want put in the return vector
	// this uses bit wise operations so you can have more then one object returned
	// use the return flags enum from the kd tree so you know what you can get back
	int ReturnParams = 0;
	int ReturnBody = 0;
	int ReturnObjects = (1<<OBJ_CORK);

	CSceneObject intakeAABB;
	intakeAABB.SetCollidableObject( &m_abTarget );

	// call the kd tree and get the near objects
	// call the kd tree and get the near objects
	CKdTree::GetNearObjects ( &intakeAABB, PSFLAG_AABB, ReturnParams, NearestObjects, ReturnBody, ReturnObjects );
	//intakeAABB.SetCollidableObject( NULL );
	vec2f Direction;
	vec2f CP;
	for( unsigned int objindex = 0; objindex < NearestObjects.size(); ++objindex )
	{
		// get the collision component of the object
		CComponent_Collision* curCollision = (CComponent_Collision*)(((IBaseObject*)NearestObjects[objindex]))->GetComponent (ECOMP_COLLISION);
		// get the collision volume of the object
		CCollisionVolume* curVolume = NearestObjects[objindex]->GetCollidableObject();
		// Safety Check
		if( curVolume && curCollision && curCollision != this )
		{	
			if( m_bCorked )
			{
				break;
			}			
			// We have collided
			// Do stuff to the object
			if( ((Box*)curVolume)->BoxToAABB( m_abTarget, CP, Direction ) )
			{
													
				// We have collided
				// get the plug's collision component
				// so we can move it
				m_pCork = curCollision;
				// set this flag
				// so we can move the plug
				// in update
				m_bIsGettingCorked = true;				
			}
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CheckLoS():	This function looks at the player and sees if the player is in range and in line of sight.
//
// Returns:		bool = true if the player is in line of sight
//
// Mod. Name: Josh Morgan
// Mod. Date:8/14/12
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CSlimeMonsterIdleAI::CheckLoS(void)
{
	//creating the sound sphere
	Sphere LoSRadius;
	LoSRadius.SetRadius(LOS_BUBBLE);
	LoSRadius.SetCenter(m_pParentObject->GetWorldPos());
	CSceneObject LoSSphere;
	LoSSphere.SetCollidableObject(&LoSRadius);

	// create a return vector to hold all the objects the kd tree returns
	std::vector <CSceneObject*> ReturnVector;
	// create a unsigned int that will tell the kd tree what you want put in the return vector
	// this uses bit wise operations so you can have more then one object returned
	// use the return flags enum from the kd tree so you know what you can get back
	int ReturnParams = 0;
	int ReturnBody = 0;
	int ReturnObjects = 1<<OBJ_PLAYER | 1<<OBJ_WORLD_COLLISION;

	CKdTree::GetNearObjects(&LoSSphere, PSFLAG_SPHERE, ReturnParams, ReturnVector, ReturnBody, ReturnObjects);

	//bool for checking if there's the player, and the position of the player
	bool bPlayerInRange = false;
	vec3f tPlayerPos = vec3f(0.0f, 0.0f, 0.0f);

	for(unsigned int i = 0; i < ReturnVector.size(); i++)
	{
		IBaseObject* pObject = ((IBaseObject*)ReturnVector[i]);

		if(pObject->GetType() == OBJ_PLAYER)
		{
			bPlayerInRange = true;
			tPlayerPos = pObject->GetWorldPos();
			break;
		}
	}

	if(!bPlayerInRange)
	{
		return false;
	}

	//we make a line to the player since he's in aggro range
	CSceneObject soLineSceneObject;
	Line LineToPlayer;
	LineToPlayer.SetVolumeType(VMT_LINE);
	LineToPlayer.SetStartPoint(vec3f(m_pParentObject->GetWorldPos().x, m_pParentObject->GetWorldPos().y + 100.0f, m_pParentObject->GetWorldPos().z));
	LineToPlayer.SetEndPoint(vec3f(tPlayerPos.x, tPlayerPos.y + 100.0f, tPlayerPos.z));
	soLineSceneObject.SetCollidableObject(&LineToPlayer);

	CKdTree::GetNearObjects(&soLineSceneObject, PSFLAG_LINE, ReturnParams, ReturnVector, ReturnBody, ReturnObjects); 

	soLineSceneObject.SetCollidableObject(nullptr);

	//loop through all the return objects again and check collision with them.
	for(unsigned int i = 0; i < ReturnVector.size(); ++i)
	{
		IBaseObject* pObject = ((IBaseObject*)ReturnVector[i]);
		
		if(pObject->GetType() == OBJ_WORLD_COLLISION)
		{
			//check to see if our line to the player is obstructed by this ocject
			vec3f Intersection = vec3f(FLT_MAX, FLT_MAX, FLT_MAX);
			if(LineToPlayer.LineToAABB(*((AABB*)pObject->GetCollidableObject()), Intersection))
			{
				//D3DXMATRIX mat;
				//D3DXMatrixIdentity(&mat);
				//mat._41 = Intersection.x;
				//mat._42 = Intersection.y;
				//mat._43 = -500;
				//DebugShapes::RenderSphere(mat);

				//we see that there's something between us so I don't have line of sight
				return false;
			}
		}
	}

	//set the slime monster to face the player
	matrix4f _localMat = (*m_pParentObject->GetLocalMat());
	matrix4f rotationMatrix;
	vec2f DtoP = LineToPlayer.GetEndPoint2D() - LineToPlayer.GetStartPoint2D();
	if(DtoP.x <= 0.0f)
	{
		//spawn facing left
		rotationMatrix.make_rotation_y( D3DXToRadian(90) );
	}
	else
	{
		//spawn to face right
		rotationMatrix.make_rotation_y( D3DXToRadian(-90) );
	}
	rotationMatrix.axis_pos = _localMat.axis_pos;
	_localMat = rotationMatrix;
	m_pParentObject->SetLocalMat(&_localMat);
	//I SEE HIM! HE'S RIGHT THERE!
	return true;
}