#include "rp.h"
#pragma hdrstop

#include "rpdirect.h"
#include "..\munga\mission.h"
#include "..\munga\app.h"
#include "..\munga\nttmgr.h"
#include "rpplayer.h"

//#############################################################################
// Shared Data support
//
Derivation* RPCameraDirector::GetClassDerivations()
{	static Derivation classDerivations(CameraDirector::GetClassDerivations(), "RPCameraDirector");
	return &classDerivations;
}


RPCameraDirector::SharedData
	RPCameraDirector::DefaultData(
		RPCameraDirector::GetClassDerivations(),
		RPCameraDirector::MessageHandlers,
		RPCameraDirector::GetAttributeIndex(),
		RPCameraDirector::StateCount,
		(CameraDirector::MakeHandler) RPCameraDirector::Make
	);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	RPCameraDirector::BeARPDirector(Scalar time_slice)
{
	Check(this);

	Player::PlayerSimulation(time_slice);
	UpdateHUD(time_slice);
	Logical force_target = False;

	//
	//--------------------------------------------------------------
	// Time To Cut To  a new Player? (Don't stay on a burning mech!)
	//--------------------------------------------------------------
	//
	if (timeLeftOnPlayer > 0.0f && application->GetApplicationState() == Application::RunningMission)
	{
		timeLeftOnPlayer -= time_slice;
		return;
	}
	else if (application->GetApplicationState() == Application::EndingMission)
	{
		force_target = True;
	}

	//
	//--------------------------------------------------------------------
	// Look for out target.  If we are not in football, follow the leader.
	// If we are in martian football, follow the losing runner
	//--------------------------------------------------------------------
	//
	Player *top_dog;
	Scalar new_time;
	if (!martianFootball || application->GetSecondsRemainingInGame() < 30.0f)
	{
		top_dog = FindPlayerByRank(0);
		new_time = 0.0f;
	}
	else
	{
		Check(application);
		EntityManager *entity_mgr = application->GetEntityManager();
		EntityGroup *player_group = entity_mgr->FindGroup("Players");
		top_dog = NULL;
		new_time = 20.0f;
		if (player_group)
		{
			RPPlayer
				*player,
				*first_player=NULL;
			ChainIteratorOf<Node*> iterator(player_group->groupMembers);
			while ((player = (RPPlayer*)iterator.ReadAndNext()) != NULL)
			{
				Check(player);
				if (player->playerType == RPPlayer::RunnerPlayerType)
				{
					if (!first_player)
					{
						first_player = player;
					}
					if (player->GetPlayerVehicle() == GetGoalEntity())
					{
						while ((player = (RPPlayer*)iterator.ReadAndNext()) != NULL)
						{
							Check(player);
							if (player->playerType == RPPlayer::RunnerPlayerType)
							{
								top_dog = player;
								break;
							}
						}
					}
				}
			}
			if (!top_dog && first_player)
			{
				top_dog = first_player;
			}
		}
	}

	//
	//-------------------------------------------------------------------
	// If we have a goal, and it is different from the last one, tell the
	// cameras
	//-------------------------------------------------------------------
	//
	if (top_dog)
	{
		Check(top_dog);
		Entity *vehicle = top_dog->GetPlayerVehicle();
		if (vehicle)
		{
			Check(vehicle);
			Entity *goalEntity = GetGoalEntity();
			if (goalEntity != vehicle || force_target)
			{
				SetGoalEntity(vehicle);
				timeLeftOnPlayer = new_time;
				Check(cameraShip);
				CameraShip::DirectionMessage direction_message(
					CameraShip::DirectionMessageID,
					sizeof(CameraShip::DirectionMessage),
					GetGoalEntity()->GetEntityID(),
					0.0f,
					Point3D::Identity
				);
				Check(cameraShip);
				cameraShip->Dispatch(&direction_message);
			}
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	RPCameraDirector::CreateRPCameraShip(Scalar time_slice)
{
	Check(this);

	CameraDirector::CreateCameraShip(time_slice);
	SetPerformance(&RPCameraDirector::BeARPDirector);
}

//#############################################################################
// Construction and Destruction Support
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RPCameraDirector::RPCameraDirector(
	RPCameraDirector::MakeMessage *creation_message,
	RPCameraDirector::SharedData &virtual_data
) :
	CameraDirector(creation_message, virtual_data)
{
	Check_Pointer(creation_message);
	currentWatchedPlayer = NULL;
	Check(application);
	CString scenarion_name = application->GetCurrentMission()->GetScenarioName();
	martianFootball = !scenarion_name.Compare("football");
	if (GetInstance() != ReplicantInstance)
	{
		SetPerformance(&RPCameraDirector::CreateRPCameraShip);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RPCameraDirector*
	RPCameraDirector::Make(MakeMessage *creation_message)
{
	return new RPCameraDirector(creation_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RPCameraDirector::~RPCameraDirector()
{

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	RPCameraDirector::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}
