/**
* Processes the state
*   changes the tower's state to attack if enemy is close
*
* @author				Cameron MacIntosh
* @param _fDeltaTick	Time between frames
*/
void
CTowerIdle::Process(float32 _fDeltaTick)
{
    // check through all tanks that are on the same face as this player.
    for (uint32 ui = 0; ui < 8; ++ui)
    {
        CTank* pTank = CPlayerManager::GetPlayerManagerInstance().GetPlayer(ui)->GetTank();

        if ((pTank->GetFacePosition() == m_pTower->GetFacePosition()) && (pTank->GetTeam() != m_pTower->GetTeam()) )
        {
            m_pTower->SetAIState(TOWERAI_STATE_ATTACK);
        }
    }

    //if an enemy moves close, switch to Attack
    m_pTower->SetAIState(TOWERAI_STATE_ATTACK);
}
/*
* Initialises the class instance
*
* @author				Cameron MacIntosh
* @param _pOwner		the owning AIPlayer
* @param _pMove			an address of an instance of the Move substate
* @param _pFlee			an address of an instance of the Flee substate
* @param Attack			an address of an instance of the Attack substate
* @return				if it succeded. Don't use the instance if it returns false.
*/
bool CAIStateProtectPlayer::Initialise(CAIPlayer* _pOwner, CAISubstateMove* _pMove, CAISubstateFlee* _pFlee,
		CAISubstateAttack* _pAttack)
{
	if(_pOwner!=0)
	{
		m_pOwner = _pOwner;
		m_pTank = m_pOwner->GetTank();

		m_pMove = _pMove;
		m_pFlee = _pFlee;
		m_pAttack = _pAttack;

		InitGeneral();

		for(uint32 i=0; i<8; ++i)
		{
			CTank* pTank = CPlayerManager::GetPlayerManagerInstance().GetPlayer(i)->GetTank();
			if((m_eEnemyTeam!=pTank->GetTeam())&&(pTank!=m_pTank))
			{
				if(pTank->HasFlag())
				{
					//carrier has flag
					m_pFlagCarrier = pTank;
					D3DXVECTOR2 vec2 = pTank->GetPosition2D();
					m_TTargetLastPos2.x = static_cast<int32>(vec2.x);
					m_TTargetLastPos2.y = static_cast<int32>(vec2.y);
					m_pMove->SetTarget(m_TTargetLastPos2.x, m_TTargetLastPos2.y, pTank->GetFacePosition());
				}
			}
		}
		if(m_pFlagCarrier==0)
		{
			m_pOwner->RequestState(AI_STATE_IDLE);
			return(false);
		}
		return(true);
	}
	return(false);
}
//overall code by rigardt, turret rotation by Cameron
void CAISubstate::FireAtEnemy()
{
	//#ifndef _AI_NOSHOOT
	// should probably be placed in substate.cpp, or substateAttack.cpp
	// as this is supposed to only be a container for the current state(s),\
	//  and not make decisions itself.
    D3DXVECTOR3 vec3Distance;
	D3DXVECTOR3 vec3ShootDir;
	D3DXVECTOR3 vec3ShootRight;

    CTank* pTankTarget = 0;
	bool m_bWillShoot = false;

    // check through all tanks that are on the same face as this player.
    for (uint32 ui = 0; ui < 8; ++ui)
    {
	    // get pointer to a tank.
	    CTank* pTank = CPlayerManager::GetPlayerManagerInstance().GetPlayer(ui)->GetTank();

	    // make sure that the tank is not equal to this one.
	    if (m_pTank != CPlayerManager::GetPlayerManagerInstance().GetPlayer(ui)->GetTank() )
	    {
		    if (pTank->GetAlive() &&
			    pTank->GetPowerUp() != POWERUP_INVISIBILITY &&
                pTank->GetTeam() != m_pTank->GetTeam() &&
			    pTank->GetFacePosition() == m_pTank->GetFacePosition() &&
                !m_pTank->HasFlag())
            {
                // the tank found a target and will shoot at it at this point.
		        m_bWillShoot = true;
		        vec3ShootDir = pTank->GetPosition() - m_pTank->GetPosition();

		        if (D3DXVec3Length(&vec3Distance) > D3DXVec3Length(&vec3ShootDir) )
		        {
                    // sets the shoot directions and the target tank.
			        vec3Distance = vec3ShootDir;
                    pTankTarget = pTank;
		        }
			    
            }
	    }
    }

    // transforms the right coords.
    D3DXMATRIX mat;

    D3DXMatrixRotationAxis(&mat, &g_atUpRightDirectionVecs[m_pTank->GetFacePosition()].vec3Up, D3DXToRadian(90) );
    D3DXVec3TransformCoord(&vec3ShootRight, &vec3Distance, &mat);

	//vec3Distance += (vec3ShootRight*((RandomFloat()-0.5f)*0.5f));

    std::vector<CWall*> rvecWalls;

    if (!m_pTank->HasFlag())
    {
        // checks if the target exsists.
        if (pTankTarget)
        {
            std::vector<CWall*> rvecWallsOnFace;

            // declare some base variables.
            float32 fXTarget = pTankTarget->GetPosition2D().x;
            float32 fYTarget = pTankTarget->GetPosition2D().y;
            float32 fXPosition = m_pTank->GetPosition2D().x;
            float32 fYPosition = m_pTank->GetPosition2D().y;
            float32 fXMin = 0.0f;
            float32 fXMax = 0.0f;
            float32 fYMin = 0.0f;
            float32 fYMax = 0.0f;

            // set the x min and max
            if (fXTarget < fXPosition)
            {
                fXMin = fXTarget - 0.5f;
                fXMax = fXPosition + 0.5f;
            }
            else
            {
                fXMax = fXTarget + 0.5f;
                fXMin = fXPosition - 0.5f;
            }
            // set the y min and max
            if (fYTarget < fYPosition)
            {
                fYMin = fYTarget - 0.5f;
                fYMax = fYPosition + 0.5f;
            }
            else
            {
                fYMax = fYTarget + 0.5f;
                fYMin = fYPosition - 0.5f;
            }

            // local variable is destroyed after these braces
            {
                std::vector<CWall*> rvecWalls = CPathfinder::GetInstance().GetCube()->GetWalls();
                for (uint32 ui = 0; ui < rvecWalls.size(); ++ui)
                {
                    // checks the wall is on the same face as the tank.
                    if (rvecWalls[ui]->GetFacePosition() == m_pTank->GetFacePosition() )
                    {
                        // adds the wall in the vector of walls to be referenced.
                        rvecWallsOnFace.push_back(rvecWalls[ui]);
                    }
                }
            }

            // checks through all the walls that are on the same face as the tank.
            for (uint32 ui = 0; ui < rvecWallsOnFace.size(); ++ui)
            {
                // This is the check to see if the walls are inside the square made by the two tanks.
                if (rvecWallsOnFace[ui]->GetX() >= fXMin && rvecWallsOnFace[ui]->GetX() <= fXMax &&
                    rvecWallsOnFace[ui]->GetY() >= fYMin && rvecWallsOnFace[ui]->GetY() <= fYMax)
                {
                    // adds the wall into the a new vector of walls.
                    rvecWalls.push_back(rvecWallsOnFace[ui]);
                }
            }
        }

        // checks if the vector is empty.
        if (!rvecWalls.empty() )
        {
            //for (uint32 ui = 0; ui < rvecWalls.size(); ++ui)
            //{
            //    // checks if the shoot direction ray intersects with any of the wall  
            //    // that are in the vector.
            //    if (TRUE == D3DXBoxBoundProbe(&rvecWalls[ui]->GetBoundingBox().m_vec3Min, 
            //                                    &rvecWalls[ui]->GetBoundingBox().m_vec3Max, 
            //                                    &m_pTank->GetPosition(), &vec3ShootDir) )
            //    {
                    // if even one wall intersects the tank will not shoot.
                    m_bWillShoot = false;
                    //break;
                //}
            //}
		}

	    // actually shoot now
	    if (m_bWillShoot == true)
	    {
			D3DXVec3Normalize(&vec3ShootDir, &vec3Distance);
			D3DXVec3Normalize(&vec3ShootRight, &vec3ShootRight);
			//m_pTank->SetShootRightAndDir(vec3ShootDir, vec3ShootRight);

			//rotates the turret - Cameron
			D3DXVECTOR2 vec2;
			EFacePosition eFace = m_pTank->GetFacePosition();
			vec2.x = D3DXVec3Dot(&vec3ShootDir, &g_atUpRightDirectionVecs[eFace].vec3Right);
			vec2.y = D3DXVec3Dot(&vec3ShootDir, &g_atUpRightDirectionVecs[eFace].vec3Direction);
			m_pTank->RotateTurret(vec2.x, vec2.y, 0.5f);
			//

            int32 iRandomChanceValue = static_cast<int32>(RandomFloat() * 300);
            if (m_pTank->GetEMPCount() == 0)
            {
                m_pTank->ShootPlasma();
            }
            else if (iRandomChanceValue >= 1)
            {
		        m_pTank->ShootPlasma();
            }
            else if (D3DXVec3LengthSq(&vec3Distance) <= 18.0f)
            {
                m_pTank->ShootEMP();
            }
            else
            {
                m_pTank->ShootPlasma();
            }
	    }
    }

	//#endif //_AI_NOSHOOT
}