/*************************************************************************
  Crytek Source File.
  Copyright (C), Crytek Studios, 2001-2004.
 -------------------------------------------------------------------------
  $Id$
  $DateTime$
  Description: Implements the player.
  
 -------------------------------------------------------------------------
  History:
  - 29:9:2004: Created by Filippo De Luca

*************************************************************************/
#ifndef __G4PLAYER_H__
#define __G4PLAYER_H__

#if _MSC_VER > 1000
# pragma once
#endif

#include "Player.h"
#include <IActionMapManager.h>

class CAutoCombat;
struct SPlayerView; // Struct for refactoring the view code

#include "PlayerActionMap.h"


// Contains all available information for cover mode
struct SCover
{
	Vec3 vCoverDir;
	EntityId idCover;
	Vec3 vNormal;
	float dist;
};

// Various modes the player can be in that affect user control and the camera.
struct SModes
{
	bool bTransition;
	bool bCoverMode;
	bool bCombatMode;
	bool bFirstPersonStaticMode;
};

// Contains information relating to the current aim point.
struct SAiming
{
	float aimYaw;
	float aimPitch;

	EntityId idTarget;

	float aimYawRange;
	float aimPitchRange;

	Vec3 vRefDir;	// aimYaw is relative to this dir

	bool bHaveTurnDir;
	Vec3 vTurnDir;
};

struct SPlayerActionQueueNode
{
	string strAction;
	int mode;
	float value;
};

#include <deque>

typedef std::deque<SPlayerActionQueueNode> TPlayerActionQueue;

class CPlayerInputG4;
class CPlayerG4 :
	public CPlayer
{
	friend class CNetworkPlayer;
  friend class CFilmCamera;       // temp hack
  friend class CFilmDirector;     // temp hack

	// temp for CScriptBind_ActorG4::AttachToActor access to m_modelOffset and m_charLocalMtx
	friend class CScriptBind_ActorG4;

	friend class CPlayerInputG4;
	friend class CPlayerViewG4;

public:

	CPlayerG4();
	virtual ~CPlayerG4();

	virtual void ProcessEvent(SEntityEvent& event);

	virtual bool Init( IGameObject * pGameObject );
	virtual void EditorToGameMode();
	virtual void Update(SEntityUpdateContext& ctx, int iUpdateSlot);
	virtual void UpdateView(SViewParams &viewParams);

	virtual void Revive( bool fromInit );

	virtual void PushActionQueue(const char *actionName, int activationMode, float value);
	virtual bool PopActionQueue(string & strAction, int & activationMode, float & value);
	virtual void ClearActionQueue();

	//virtual void OnAction(const ActionId& actionId, int activationMode, float value);
	//virtual void OnAction(const char *actionName, int activationMode, float value);
	virtual void AfterAction();

	//virtual void Serialize( TSerialize ser );
	//virtual void SerializeXML( XmlNodeRef& node, bool bLoading );
  
  //virtual void SetActorMovement(SOBJECTSTATE &control);

//virtual void SetAngles(const Ang3 &angles);
//virtual Ang3 GetAngles();

	//virtual void ProcessRotation(float frameTime);
	//virtual void ProcessMovement(float frameTime);

  //virtual void SetDesiredSpeed(const Vec3 &desiredSpeed);
  //virtual void SetDesiredDirection(const Vec3 &desiredDir);
  //virtual Vec3 GetDesiredDirection();

	SAiming &GetAiming() { return m_aiming; }
	
  void BeginPlayerCameraCut();
  void EndPlayerCameraCut();
  void SetWeaponTargetDir(const Vec3 &vDir,int iHand=1)   // 0 = left hand, 1 = right hand. Right hand is also used for 2 handed weapons.
    {  if(iHand>=0 && iHand <=1) m_vWeaponTarget[iHand]=vDir.GetNormalized(); }
  Vec3 GetWeaponTargetDir(int iHand=1)              // 0 = left hand, 1 = right hand. Right hand is also used for 2 handed weapons.
    {  if(iHand>=0 && iHand <=1) return m_vWeaponTarget[iHand]; else return Vec3(0,1,0); }
  void SetWeaponTargetDist(float dist,int iHand=1)   // 0 = left hand, 1 = right hand. Right hand is also used for 2 handed weapons.
  {  if(iHand>=0 && iHand <=1) m_weaponTargetDist[iHand]=dist; }
  float GetWeaponTargetDist(int iHand=1)              // 0 = left hand, 1 = right hand. Right hand is also used for 2 handed weapons.
  {  if(iHand>=0 && iHand <=1) return m_weaponTargetDist[iHand]; else return 0.0f; }

  CAutoCombat *GetAutoCombat() { return m_pAutoCombat; }


	bool IsCombatMode();
	void SetCombatMode(bool bSet);

  void CinematicDeathAct(const char *psDeathAct);

	void GetEyePosDir(Vec3 &rvEyePos,Vec3 &rvEyeDir);

  bool m_bCameraCut;
protected:
	CAutoCombat *m_pAutoCombat;
  Vec3 m_vWeaponTarget[2];
  float m_weaponTargetDist[2];
	//Matrix33 m_viewMtxFinal; This member of CPlayer is effectively the player models view matrix.
	Matrix33 m_camViewMtxFinal;	// This one is the cameras final view matrix.

  // Hacks for init's that 'need' to be called after a few ticks of player instantiation.
  bool m_bLateInit;
  int m_lateInitCount;
  // Camera editing
  bool m_bEditCam;
  int m_oldCamMode;
  bool m_bCinematicDeathMovement;	// This guys doing something a little special as he dies
  const char *m_psCinematicDeathAct;	// The special thing this guy's doing as he dies.
	float m_timeLastYawPitch;		// Used for auto return of navigations free-look camera.
	int m_nTickLastPitch;
	SCover m_cover;	// Cover mechanic.
	SModes m_modes;	// Modes player can be in that affect the camera and movement
	SAiming m_aiming;	// for the aiming system.
	bool m_bHolster;	// weapon holster state.
	bool m_bActionsEnabled;
	TPlayerActionQueue m_actionQueue;

	// Cover mechanic
	void EnterCover(const Vec3 &vCoverDir,SCover &rCover);
	void LeaveCover();
	bool IsCoverInDir(const Vec3 & vTestDir,float distTest,SCover &rCover);
	float GetCoverDist(const Vec3 & vTestDir,float distTest,SCover &rCover);
	bool GetCover(Vec3 &vCoverDir,SCover &rCover);
	void TickCover();

	// Aiming, and aiming/turning system.
	void TickAiming();

	bool IsTimeForAutoReturn();
  void PitchAutoReturn(float frameTime,float rate);
  void YawAutoReturn(float frameTime,float rate);

	float WrapAngle180(float yaw);

  // Called during update cycle to auto restore view to default position
  virtual void UpdateReturnView(SEntityUpdateContext & ctx);
  // Called via CPlayer:Update() if CPlayer is a rag doll, or is dead
  virtual void UpdateAsDoll(SEntityUpdateContext & ctx);
  // Called via CPlayer:Update() if CPlayer is alive and not a rag doll.
  virtual void UpdateAsLiveAndMobile(SEntityUpdateContext & ctx);

  // various sub views
  //virtual void UpdateViewCameraCut(SViewParams &viewParams,SPlayerView &v);
  //virtual void UpdateViewThirdPerson(SViewParams &viewParams,SPlayerView &v);
  //virtual void UpdateViewThirdPersonDamped(SViewParams &viewParams,SPlayerView &v);
  //virtual void UpdateViewPivot(SViewParams &viewParams,SPlayerView &v);
  //virtual void UpdateViewFollowHead(SViewParams &viewParams,SPlayerView &v);
  //virtual void UpdateViewFirstPerson(SViewParams &viewParams,SPlayerView &v);
  void DoCinematicDeathMovement(SOBJECTSTATE &control);

  // Camera editing
  void SaveEditCam();

	bool VerifySkeleton();

  // Accessed via function to allow game based modifiers to stance speed without multiplying the number of stances.
  virtual float GetStanceMaxSpeed(EStance stance) const;

  virtual void GetStanceAngleLimits(float & minAngle,float & maxAngle);

	static Vec3 WorldToScreenCoords(Vec3 worldPos);

	virtual IPlayerInput * CreatePlayerInput();
};


#endif //__G4PLAYER_H__
