#include	"../bot/gen_bot_header.h"
#include	"monsters.h"
#include	"talkmonster.h"
#include	"schedule.h"
#include	"defaultai.h"
#include	"scripted.h"
#include	"weapons.h"
#include	"nodes.h"
#include    "animation.h"
#include	"../engine/studio.h"
#include	"classes.h"
#include	"playermelee.h"
#include	"buddy_tasks.h"
#include	"buddy_aura.h"
#include	"buddy.h"
#include	"buddy_classes.h"
#include	"buddy_weapons.h"
#include	"hltv.h"
#include	"candy.h"
#include	"decals.h"


// Depending on m_eThreatSense we will search for different possible
// things for out buddy to worry about
long CBuddyTask::SenseThreat(CBuddy *pBuddy)
{
	// UNDONE
	CBasePlayer *pPlayer;
	CBuddy *otherBuddy;
	CBaseEntity *pEnt = NULL;
	CBaseEntity *pBestEnemy = NULL;
	float flDist, flNearestDist = 9999.0f;
	int bFound = 0;
	long lThreatLevel = 0;
	long lTestLevel = 0;

	// First look for a normal player enemy
	if (m_eSense && bsPlayers)
	{
		for(byte b=1;b<=gpGlobals->maxClients;b++)
		{
			pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(b);

			if (!UTIL_IsValidPlayer(pPlayer, true, false))
				continue;

			// Skip friends and owner
			if (((pPlayer->pev->team == pBuddy->pev->team) && g_teamplay) || (pPlayer == pBuddy->m_pOwner))
				continue;

			flDist = UTIL_Distance(pBuddy->pev->origin, pPlayer->pev->origin);
			if (flDist >= flNearestDist)
				continue;

			if (!pBuddy->FInViewCone(pPlayer) || !pBuddy->FVisible(pPlayer))
				continue;
			
			if (!pPlayer->FInViewCone(pBuddy) || !pPlayer->FVisible(pBuddy))
			{
				// he cant see us so MAYBE we'll attack him
				lTestLevel = 5;
			}
			else
			{
				if (pPlayer->m_Swoop.m_fSwoop)
					lTestLevel = 40;
				else if (pPlayer->m_fControl)
					lTestLevel = 30;
				else
					lTestLevel = 10;
			}
			
			if (lTestLevel > lThreatLevel)
			{
				lThreatLevel = lTestLevel;
				pBuddy->m_pCurrentEnemy = pPlayer;
			}
		}
	}

	// Now search for enemy buddies
	if (m_eSense && bsBuddies)
	{		
		while((pEnt = UTIL_FindEntityByClassname(pEnt, "player_buddy")) != NULL)
		{
			if (pEnt == pBuddy)
				continue;

			if (IsNull(pEnt))
				continue;

			if (!pEnt->IsAlive())
				continue;

			// Skip friends
			if ((pEnt->pev->team == pBuddy->pev->team) && g_teamplay)
				continue;

			flDist = UTIL_Distance(pBuddy->pev->origin, pEnt->pev->origin);
			if (flDist >= flNearestDist)
				continue;

			if (!pBuddy->FInViewCone(pEnt) || !pBuddy->FVisible(pEnt))
				continue;

			otherBuddy = (CBuddy*) pEnt;

			if (otherBuddy)
			{
				if (otherBuddy->m_pCurrentEnemy == pBuddy)
				{
					lThreatLevel = 20;
				}
				else
				{
					lThreatLevel = 6;
				}
			}

			if (lTestLevel > lThreatLevel)
			{
				lThreatLevel = lTestLevel;
				pBuddy->m_pCurrentEnemy = otherBuddy;
			}
		}
	}	

	//if (m_eSense && 
	//while ((pAttack = UTIL_FindEntityByString(pAttack, "globalname", "magic_attack")) != NULL)
	//{
	//}

	return lThreatLevel;
}

CBuddyTask_Follow::CBuddyTask_Follow()
{
	// just to guarantee we get to think once
	TaskState = tsCantSwitch;
	bAttack = TRUE;
	lastPos = Vector(0,0,0);
}

CBuddyTask *CBuddyTask_Follow::AttackThink(CBasePlayer *pBuddyOwner)
{
	CBuddyTask *newTask;

	if (pBuddyOwner->m_eBuddyMood == buddyMimic)
	{
		if ((pBuddyOwner->pev->button & (IN_ATTACK)) || (pBuddyOwner->pev->button & (IN_ATTACK2)))
		{
			// if our owner is struggling we dont want to do a mimic shot
			if ( (pBuddyOwner->m_pActiveItem) && (!pBuddyOwner->m_fPowerStruggling) )
			{
				switch (pBuddyOwner->m_pActiveItem->m_iId)
				{
					case WEAPON_GENERICBEAM:

						if (!pBuddyOwner->m_fControl)
						{
							newTask = new CBuddyTask_Follow_BeamCharge();
							//pBot->m_pBotCombo = new CBotCombo(pBot, CT);
							return newTask;
						}
						else
						{
							newTask = new CBuddyTask_KiBlastFire();

							return newTask;
						}

					case WEAPON_KIBLAST:
							newTask = new CBuddyTask_KiBlastFire();

							return newTask;
											
						

					//default:
						//pAttack = GetWeapon("kiblast");
				}
			}
		}
	}

	return NULL;
}

CBuddyTask *CBuddyTask_Follow::TaskThink(CBuddy *pBuddy)
{
	// ****************** NOTE ****************** 
	//
	// Follow_BeamCharge uses this class to follow! Change this to pBuddy->Follow() function so
	//// beam charge does not need to use it


	// if anyone wants to remove us then this is fine	
	TaskState = tsCanSwitch;
		
	CBasePlayer *pBuddyOwner = (CBasePlayer *)CBaseEntity::Instance(pBuddy->m_pOwner->pev);

	// if we havent moved
	if (bShouldMove == TRUE)
	{
		// and we should have moved
		//PrintAI("Tested: " << pBuddy->pev->velocity.x << "," << pBuddy->pev->velocity.y << "," << pBuddy->pev->velocity.z << "\n");
		//if ((pBuddy->pev->velocity.x > 0) || (pBuddy->pev->velocity.y > 0) || (pBuddy->pev->velocity.z > 0))
		if ((lastPos.x == pBuddy->pev->origin.x) && (lastPos.y == pBuddy->pev->origin.y) && (lastPos.z == pBuddy->pev->origin.z))
		{
			// keep track of how long we have been lost for
			lostCt++;
						
			// we're probably stuck on somehthing, isn that embarrassing?
			if (lostCt > LOST_TOO_LONG)
			{
				//CBuddyTask* newTask = new CBuddyTask_HomeThroughMap();

				//return newTask;
			}
		}
	}
	else
		lostCt = 0;

	if (pBuddyOwner->m_fPowerUp)
	{
		CBuddyTask *newTask;
		newTask = new CBuddyTask_PowerUp();

		return newTask;
	}

	if (bAttack == TRUE)
	{
		CBuddyTask *newTask;
		newTask = AttackThink(pBuddyOwner);

		// if we decided on a new task return it
		if (newTask) return newTask;

		if (pBuddy->m_pCurrentWeapon)
			pBuddy->m_pCurrentWeapon->WeaponIdle();
	}
	
	pBuddy->Follow();

	lastPos.x = pBuddy->pev->origin.x;
	lastPos.y = pBuddy->pev->origin.y;
	lastPos.z = pBuddy->pev->origin.z;

	if ((pBuddy->pev->velocity.x > 0) || (pBuddy->pev->velocity.y > 0) || (pBuddy->pev->velocity.z > 0))
		bShouldMove = TRUE;
	else
		bShouldMove = FALSE;

	return NULL;
}

CBuddyTask* CBuddyTask_Follow::ManageThreat(CBuddy *pBuddy)
{
	if (pBuddy->m_pScariestEnemy)
	{

	}

	return NULL;
}

CBuddyTask_Follow::~CBuddyTask_Follow()
{
}

void CBuddyTask_Follow::DebugPrint(CBuddy *pBuddy)
{
	PrintAI("Current Task: Follow\n");
	PrintAI("Last Pos: " << lastPos.x << "," << lastPos.y << "," << lastPos.z << "\n");
	PrintAI("Curr Pos: " << pBuddy->pev->origin.x << "," << pBuddy->pev->origin.y << "," << pBuddy->pev->origin.z << "\n");
	PrintAI("Curr Pos: " << pBuddy->pev->velocity.x << "," << pBuddy->pev->velocity.y << "," << pBuddy->pev->velocity.z << "\n");
}

// --==*************************************************************==--
//
// Follow Beam Charge start
//
// --==*************************************************************==--
CBuddyTask_Follow_BeamCharge::CBuddyTask_Follow_BeamCharge()
{
	TaskState = tsCanSwitch;
}


CBuddyTask *CBuddyTask_Follow_BeamCharge::TaskThink(CBuddy *pBuddy)
{
	if ((!pBuddy->m_pCurrentWeapon) || (!(FStrEq(pBuddy->m_pCurrentWeapon->GetWeaponName(), "genericbeam"))))
	{
		pBuddy->SetCurrentWeapon(pBuddy->GetWeapon("genericbeam"));

		if (!(FStrEq(pBuddy->m_pCurrentWeapon->GetWeaponName(), "genericbeam")))
		{	// we dont have generic beams
			CBuddyTask_Follow* newTask = new CBuddyTask_Follow();
			return newTask;
		}
	}

	CBasePlayer *pBuddyOwner = (CBasePlayer *)CBaseEntity::Instance(pBuddy->m_pOwner->pev);

	if ((pBuddyOwner->pev->button & (IN_ATTACK)) || (pBuddyOwner->pev->button & (IN_ATTACK2)))
		pBuddy->m_pCurrentWeapon->ShootPrimary();
	else
	{
		TaskState = tsCanSwitch;

		CBuddyTask *newTask = new CBuddyTask_BeamFire();
		return newTask;
	}
	
	pBuddy->AimWithOwner();

	// we can still move so we'll use the follow thinks functionality
	pBuddy->Follow();

	return NULL;
}

CBuddyTask_Follow_BeamCharge::~CBuddyTask_Follow_BeamCharge()
{

}

CBuddyTask *CBuddyTask_Follow_BeamCharge::ManageThreat(CBuddy *pBuddy)
{
	return NULL;
}

void CBuddyTask_Follow_BeamCharge::DebugPrint(CBuddy *pBuddy)
{
	PrintAI("Current Task: FollowBeamCharge");
}
// --==*************************************************************==--
//
// Follow Beam Charge end
//
// --==*************************************************************==--

// --==*************************************************************==--
//
// Fire Beam start
//
// --==*************************************************************==--
CBuddyTask_BeamFire::CBuddyTask_BeamFire()
{
	TaskState = tsCantSwitch;
	bOneThought = false;
}

CBuddyTask_BeamFire::~CBuddyTask_BeamFire()
{
}

CBuddyTask *CBuddyTask_BeamFire::ManageThreat(CBuddy *pBuddy)
{
	return NULL;
}

CBuddyTask *CBuddyTask_BeamFire::TaskThink(CBuddy *pBuddy)
{
	if ((!pBuddy->m_pCurrentWeapon) || !(FStrEq(pBuddy->m_pCurrentWeapon->GetWeaponName(), "genericbeam")))		
	{
		TaskState = tsComplete;
		return NULL;
	}

	CBasePlayer *pBuddyOwner = (CBasePlayer *)CBaseEntity::Instance(pBuddy->m_pOwner->pev);

	if (bOneThought) // we have thought once before
	{		
		if (!pBuddyOwner->m_fControl)
		{
			if (pBuddy->m_fControl == TRUE) // if we're not controlling a beam bail out!
			{
				pBuddy->m_pCurrentWeapon->ShootSecondary();
			}
			
			TaskState = tsComplete;
			return NULL;
		}

	}

	TaskState = tsCanSwitch;
	pBuddy->m_pCurrentWeapon->WeaponIdle();
	
	if (pBuddyOwner->m_eBuddyMood == buddyMimic)
	{
		pBuddy->AimWithOwner(); 
	}
	else
	{
		// we have to aim on our own here
	}

	bOneThought = true;

	return NULL;
}

void CBuddyTask_BeamFire::DebugPrint(CBuddy *pBuddy)
{
	PrintAI("Current Task: FireBeam");
}

void CBuddyTask_BeamFire::CleanUp(CBuddy* pBuddy)
{
	if (pBuddy->m_fControl == TRUE) // if we're not controlling a beam bail out!
	{
		pBuddy->m_pCurrentWeapon->m_flNextSecondaryAttack = 0;
		pBuddy->m_pCurrentWeapon->ShootSecondary();
	}
}

// --==*************************************************************==--
//
// Fire Beam end
//
// --==*************************************************************==--

// --==*************************************************************==--
//
// Fire KiBlast start
//
// --==*************************************************************==--
CBuddyTask_KiBlastFire::CBuddyTask_KiBlastFire()
{
	TaskState = tsCantSwitch;
	bOneThought = false;
}

CBuddyTask_KiBlastFire::~CBuddyTask_KiBlastFire()
{
}

CBuddyTask *CBuddyTask_KiBlastFire::ManageThreat(CBuddy *pBuddy)
{
	return NULL;
}

CBuddyTask *CBuddyTask_KiBlastFire::TaskThink(CBuddy *pBuddy)
{
	CBaseBuddyWeapon *pAttack = pBuddy->GetWeapon("kiblast");
	CBasePlayer *pBuddyOwner = (CBasePlayer *)CBaseEntity::Instance(pBuddy->m_pOwner->pev);

	// only takes one thought to finish this
	TaskState = tsComplete;

	// no weapon no fighting!	
	if (!pAttack) return NULL;

	pBuddy->SetCurrentWeapon(pAttack);
	
	// 1) aim
	if (pBuddyOwner->m_eBuddyMood == buddyMimic)
	{
		pBuddy->AimWithOwner(); 
	}
	else
	{
		// we have to aim on our own here
	}

	// 2) shoot
	switch ( RANDOM_LONG( 0, 1 ) )
	{
	case 0:
		pBuddy->m_pCurrentWeapon->ShootPrimary();
	case 1:
		pBuddy->m_pCurrentWeapon->ShootSecondary();
	}	
	
	// 3) follow and done
	// FIX ME::
	// 

	
	pBuddy->Follow();

	return NULL;
}

void CBuddyTask_KiBlastFire::DebugPrint(CBuddy *pBuddy)
{
	PrintAI("Current Task: FireKiBlast");
}
// --==*************************************************************==--
//
// Fire Kiblast end
//
// --==*************************************************************==--

// --==*************************************************************==--
//
// Power Up start
//
// --==*************************************************************==--
CBuddyTask_PowerUp::CBuddyTask_PowerUp()
{
	TaskState = tsCantSwitch;
	bPowerUpStarted = false;
}

CBuddyTask_PowerUp::~CBuddyTask_PowerUp()
{
}

CBuddyTask *CBuddyTask_PowerUp::ManageThreat(CBuddy *pBuddy)
{
	return NULL;
}

CBuddyTask *CBuddyTask_PowerUp::TaskThink(CBuddy *pBuddy)
{	
	if (bPowerUpStarted == false)
	{
		bPowerUpStarted = true;
		pBuddy->StartPowerUp();
	}

	CBasePlayer *pBuddyOwner = (CBasePlayer *)CBaseEntity::Instance(pBuddy->m_pOwner->pev);
	if (pBuddyOwner->m_eBuddyMood == buddyMimic)
	{
		if (pBuddyOwner->m_fPowerUp == false)
		{
			pBuddy->StopPowerUp();
			this->TaskState = tsComplete;
		}
	}
	else
	{
		if  (pBuddy->m_fKi >= pBuddy->m_pClass->GetMaxKi())
		{
			pBuddy->StopPowerUp();
			TaskState = tsComplete;
		}
	}

	return NULL;
}

void CBuddyTask_PowerUp::DebugPrint(CBuddy *pBuddy)
{
	PrintAI("Current Task: PowerUp\n");
}
// --==*************************************************************==--
//
// Power Up end
//
// --==*************************************************************==--