#pragma once

#include "..\munga\player.h"
#include "..\munga\damage.h"
#include "..\munga\vchain.h"

#define POINTS_SPEED_RATIO 400

class ScoreZone__ReplyMessage;
class DropZone__ReplyMessage;
class RPPlayer;

//##########################################################################
//		struct Offensive Player
//

class RPPlayer__OffensivePlayer:
	public Node
{
public:
	RPPlayer__OffensivePlayer()
		{}
	RPPlayer__OffensivePlayer(
		RPPlayer	*offensive_player,
		int		damage_type,
		Time	time_stamp
	);

	//
	//-----------------------------------
	// The player who caused the damage
	//-----------------------------------
	//
	RPPlayer
		*offensivePlayer;
	//
	//---------------------------------------------------------------
	// How many points the offensive player gets if this players dies
	//---------------------------------------------------------------
	//
	Scalar
		deathBonus;
	//
	//------------------------------------------------
	// The type of damage the offensive player caused
	//------------------------------------------------
	//
	int
		damageType;
	//
	//-------------------------------
	// Time the damage was inflicted
	//-------------------------------
	//
	Time
		timeStamp;
};

//##########################################################################
//####################   RPPlayer::StatusMessage   #########################
//##########################################################################

class RPPlayer__StatusMessage:
	public Player__StatusMessage
{
public:
	RPPlayer__StatusMessage();

	RPPlayer__StatusMessage(
		RPPlayer	*player_involved,
		int message_type,
		Scalar display_time,
		Scalar damage_amount = 0.0f
	);

	enum {
		DestroyedMessage = Player__StatusMessage::NextMessageType,
		DestroyedByMessage,
		RunnerMessage,
		BlockerMessage,
		CrusherMessage,
		ScoreZoneMessage,
		PilotErrorMessage,
     Score2xMessage,
     Score4xMessage,
     Score8xMessage,
     Score16xMessage,
     CrushedMessage = Player__StatusMessage::NextMessageType,
     CrushedByMessage,
     BlockedMessage = Player__StatusMessage::NextMessageType,
     BlockedByMessage,
     DingedMessage = Player__StatusMessage::NextMessageType,
     DingedByMessage,
		NextMessageType
	};

	Scalar
		damageAmount;

	//------------------------------------------------------
	// Memory block utilization
	//------------------------------------------------------
private:
	static MemoryBlock* GetAllocatedMemory();
	enum
	{
		numberOfAllocatedBlocks=8	// seven kills and a suicide!!!
	};

public:
	void*
		operator new(size_t)
			{return GetAllocatedMemory()->New();}
	void
		operator delete(void *where)
			{ GetAllocatedMemory()->Delete(where);}
};

//##########################################################################
//#####################    RPPlayer::MakeMessage    ########################
//##########################################################################

class RPPlayer__MakeMessage:
	public Player::MakeMessage
{
public:
	int
		teamID;

	Enumeration
		playerType;

	Logical
		scoreCompression;

	RPPlayer__MakeMessage(
		Receiver::MessageID message_ID,
		size_t length,
		Entity::ClassID class_ID,
		const EntityID &owner_ID,
		ResourceDescription::ResourceID resource_ID,
		LWord instance_flags,
		const Origin &origin,
		int	player_bitmap_index,
		int   player_type,
		int	team_ID,
		Logical score_compression
	):
		Player::MakeMessage(
			message_ID,
			length,
			class_ID,
			owner_ID,
			resource_ID,
			instance_flags,
			origin,
			player_bitmap_index
		),
		teamID(team_ID)
			{ playerType = player_type; scoreCompression = score_compression;}

	RPPlayer__MakeMessage(
		Receiver::MessageID message_ID,
		size_t length,
		const EntityID &entity_ID,
		Entity::ClassID class_ID,
		const EntityID &owner_ID,
		ResourceDescription::ResourceID resource_ID,
		LWord instance_flags,
		const Origin &origin,
		int	player_bitmap_index,
		int	player_type,
		int	team_ID,
		Logical score_compression
	):
		Player::MakeMessage(
			message_ID,
			length,
			entity_ID,
			class_ID,
			owner_ID,
			resource_ID,
			instance_flags,
			origin,
        player_bitmap_index
		),
		teamID(team_ID)
			{ playerType = player_type; scoreCompression = score_compression;}
};

class RPPlayer__ScoreMessage:
	public Player::ScoreMessage
{
	public:
		int
			scoreType;

		EntityID
			pointSender;

		RPPlayer__ScoreMessage(
		  Receiver::MessageID message_ID,
		  size_t length,
		  int score_type,
		  Scalar	score_award,
		  EntityID point_sender
		):
			Player::ScoreMessage(message_ID, length, score_award)
		{
			scoreType = score_type;
			pointSender = point_sender;
		}
};


//##########################################################################
//###########################    Player    ################################
//##########################################################################

class RPPlayer:
	public Player
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
	static Derivation *GetClassDerivations();
	static SharedData DefaultData;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
enum {
	ScoreZoneReplyMessageID = Player::NextMessageID,
	NextMessageID
};
private:
	static const HandlerEntry MessageHandlerEntries[];

protected:
	//static MessageHandlerSet MessageHandlers;
	static MessageHandlerSet& GetMessageHandlers();
	void MissionEndingMessageHandler(Message *message);
	void MissionStartingMessageHandler(Message *message);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Vehicle creation
//
public:
	typedef RPPlayer__ScoreMessage				ScoreMessage;
	typedef RPPlayer__OffensivePlayer			OffensivePlayer;
	typedef RPPlayer__MakeMessage					MakeMessage;
	typedef RPPlayer__StatusMessage				RPStatusMessage;

protected:
	virtual void
		DropZoneReplyMessageHandler(
			DropZone__ReplyMessage *message
		);

	virtual void
		ScoreZoneReplyMessageHandler(
			ScoreZone__ReplyMessage *message
		);

	void
		VehicleDeadMessageHandler (VehicleDeadMessage *message);

	virtual void
		TakeDamageMessageHandler (TakeDamageMessage *message);

	virtual void
		ScoreMessageHandler(ScoreMessage *message);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//		Damage Points Support
//

	VChainOf<OffensivePlayer*, Enumeration>
		offensivePlayerList;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
	enum{
		GoalEntityAttributeID = Player::NextAttributeID,
		NextAttributeID
	};

	Entity
		*goalEntity;

private:

	static const IndexEntry AttributePointers[];

protected:

	//static AttributeIndexSet	AttributeIndex
	static AttributeIndexSet& GetAttributeIndex();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
	typedef void
		(RPPlayer::*Performance)(Scalar time_slice);

	void
		SetPerformance(Performance performance)
		{
			Check(this);
			activePerformance = (Simulation::Performance)performance;
		}

	void
		PlayerSimulation(Scalar time_slice);


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
	static RPPlayer*
		Make(MakeMessage *creation_message);

	RPPlayer(
		MakeMessage *creation_message,
		SharedData	&shared_data = DefaultData
	);
	~RPPlayer();

	Logical
		TestInstance() const;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//		Local data
//
public:
	enum PlayerType{
		GeneralPlayerType,
		RunnerPlayerType,
		CrusherPlayerType,
		BlockerPlayerType,
		CameraShipPlayerType
	} playerType;

	enum {
		NullPointType = 0,
		ScoreZonePointType,
		DeathBonusPointType,
		DeathScoreLossPointType,
		DamageBonusPointType,
		DamageScoreLossPointType,
		SpeedBonusPointType,
		CrusherScorePointType,
		DropZoneHitType,
		DropZoneKillType,
		OutOfBoundsType,
		PointTypeCount
	};

	virtual void
		AddOffensivePlayer(OffensivePlayer &offensive_player);

	int
		teamID;

	int
		CalcRanking();

	void
  	CalcFootballRanking();

	virtual Vector3D
		GetWorldLinearVelocity()
     	{return Vector3D(0,0,0);}

protected:
//
//	protected Interface
//

	void
		DeleteAllOffensivePlayers();

	RPPlayer*
		GetPlayer(EntityID playerID);

	void
		CleanUpOffensivePlayers();

	void
		CreatePlayerVehicle(Origin);

	void
		ResetAfterDeath(DropZone__ReplyMessage *message);

	void
		InitializePlayerLink();

	void
		SetGoalToFirstScoreZone();

	virtual void
		PointVTVTowardGoal();

	void
		AccumulateSpeedPoints(Scalar time_slice);

	Logical
		scoreCompression;

	Time
		lastConsoleUpdate;
};
