#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef _TOOLS_CUTSCENEACTOR_OBJECT_H_
#define _TOOLS_CUTSCENEACTOR_OBJECT_H_

#include "Animation/Asura_Animation.h"
#include "Core/Asura_String.h"
#include "Core/Asura_Hash.h"
#include "Cutscene/Asura_Cutscene_Camera_Shake.h"

#include "Objects/Tools_Object.h"
#include "Objects/Tools_Object_System.h"
#include "Tools_Undo.h"

class Asura_Cutscene_Actor;
class Tools_Cutscene_Object;
class Tools_Cutscene_Track;
class Asura_Cutscene_Track;
class Asura_Hierarchy_Anim;
class Tools_Cutscene_Attachment;
class Asura_Cutscene_Attachment;

class Tools_CutsceneActor_Object : public Tools_Object
{
	public :
		Tools_CutsceneActor_Object(Asura_Cutscene_Actor* actor,Tools_Cutscene_Object* cutsceneObject);
		~Tools_CutsceneActor_Object();

		virtual void Initialise();


		//virtual function overides
		const char* GetName();
		const char* GetTypeDescription();
		void Destroy();
		void OnSelection();
		void OnDeselection();
		bool IsHidden();
		void UpdatePositionInAsuraData(bool updateLinkedObjects /*=true*/);
		virtual void AddContextMenuItems(class Tools_ContextMenu& xMenu, const class Tools_ContextMenu_Context& xContext);
		Asura_Guid GetGuid() const;
		virtual bool ObjectIsInLOS(const Asura_Vector_3& alpha, const Asura_Vector_3& beta, float& lowest);
		virtual bool ShouldTestForLOS();
		virtual bool ShouldHideDuringCutscene(){return false;}
		virtual bool ShouldBeRendered();
		bool ShouldShowToolsObjectMesh();

		
		void CreateOverlay();
		void DeleteOverlay();
		virtual void AddOverlayControls(class Asura_Overlay* newOverlay,class Asura_Vector_2& offset);
		void UpdateOverlay();//updates labels etc on overlay

		static void ToggleOverlay(void);
		static bool OverlayIsOn(void);


		static void CreateTrack();
		virtual class Tools_Cutscene_Track* CreateTrack(int trackID);
		void SortTracks();

		static void CreateAttachmentForCurActorObj( void );
        virtual Tools_Cutscene_Attachment* CreateAttachment( void );

		static void EditAttachment();

		static bool IsEnabled_ChooseSkin(int iSkinIndex);
		static void ChooseSkin(int iSkinIndex);
		static void ChooseAnim();
		static void ChooseShape();
		static void ChooseCameraTarget();
		static void _Rename();
		static void _EditEvents();
		static void EditInitialAnim();
		static void RecordAnimation();
		void Rename(const char* name = NULL);

		static void ChooseTexture(int iThis){((Tools_CutsceneActor_Object*)iThis)->ChooseTexture();}
		void ChooseTexture();
		static void ClearTexture(int iThis){((Tools_CutsceneActor_Object*)iThis)->ClearTexture();}
		void ClearTexture();
			
		static void SetInitialCamera(int iThis){((Tools_CutsceneActor_Object*)iThis)->SetInitialCamera();}
		void SetInitialCamera();


		virtual void OnSkinChange(){};

		bool ChooseAnim(int& animIndex);
		bool ChooseAnim(const char* message,Asura_String& szAnimName,Asura_String& szFileName);
		Asura_Hierarchy_Anim* ChooseAnim(const char* message);

		void UpdatePositionFromTrack();

		virtual void RemoveTrackFromActor(Asura_Cutscene_Track* track);
        virtual void NotifyToolsTrackDeleted(Tools_Cutscene_Track* pxToolsTrack);
		void RemoveAttachmentFromActor(Asura_Cutscene_Attachment* pxAttachment);
		void UpdateTracks();

		void GetPositionAtTime(float time,Asura_Vector_3* outputPosition);

		void ListObjectsForActor(List<Tools_Object*>& xObjectList);
		static void ContextMenu_SelectActor(void* pObject, u_int uMode);

		virtual bool IsHierarchyActor();
		virtual bool IsShapeActor();
		virtual bool IsCameraActor();
		virtual bool IsCameraTargetActor();

		virtual void UpdateCutsceneEdit();

		void SelectAttachment(int iIndex);
		void UpdateAttachmentSelection();
		u_int GetNextAttachmentID(){return ++m_uHighestAttachmentID;}

		static void CopyTracks();
		void CopyTracks(Asura_Cutscene_Actor* pxAsuraActor);

		void UpdateSoundPosition();

		virtual bool NeedsGuid() { return true; }	// allows derived classes to prevent assignment of guid in Initialise();

		//gets the name of one of the variables that differ from the backups
		const char* GetNameOfChangedVariable();

		static void ChooseEntityToReplace();
		void SetEntityToReplace(Asura_Guid uGuid);



		//data
		Asura_Cutscene_Actor* Actor;
		Tools_Cutscene_Object* CutsceneObject;
		List<Tools_Cutscene_Track*> Tracks;
		Asura_String AnimDirectoryName;

		List<Tools_Cutscene_Attachment*> m_xAttachmentList;
		Tools_Cutscene_Attachment* m_pxSelectedAttachment;

		int m_iSelectedAttachmentIndex;
		bool m_bSelectedAttachmentIndexChanged;
		u_int m_uHighestAttachmentID;


		bool m_bChanged;

		bool m_bHiddenInTimeline;//hides actor on timeline screen.


		//backup for undo
		int m_iAnimationFlagsBackup;
		float m_fAnimationDelayBackup;
		u_int m_uActorFlagsBackup;
		u_int m_uHierarchyFlagsBackup;
		u_int m_uShapeFlagsBackup;
		Asura_Hash_ID m_uTextureHashBackup;
		Asura_Hash_ID m_uIKTemplateIDBackup;
		#ifdef ASURA_USE_FACIAL_ANIMATION_SYSTEM
		Asura_Hash_ID m_uFaceIDBackup;
		#endif
		u_int m_uCameraFlagsBackup;
		Asura_Angle m_fInitialFOVBackup;
		float m_fNearClipBackup;
		float m_fFarClipBackup;
		Asura_Guid m_uGuidToReplaceBackup;
		bool m_bHandheldCameraEnabled;
		Asura_Cutscene_Camera_Shake m_xCameraShakeBackup;

		//overlay
		static Asura_Vector_2 OverlayPosition;
		static Tools_CutsceneActor_Object* ThisActor;//(a 'this' substitute for functions called by the overlay)
		static bool	OverlayOpen;

		enum DialogID
		{
			DialogID_Skin0,
			DialogID_SkinLast = DialogID_Skin0+99,//somewhat excessive , but what the hell
			DialogID_Anim,
			DialogID_Shape,
			DialogID_Texture,
			DialogID_ClearTexture,
			DialogID_CameraTarget,
			DialogID_GuidToReplace,
		};

		//for use while recording wav files
		Asura_Vector_3 m_xSoundPosition;

		Tools_ChooseObject* m_pxChooseObject;

    protected:
		static bool _CameraAllowsPlayerControl() { return ThisActor->CameraAllowsPlayerControl(); }
		bool CameraAllowsPlayerControl();

		static bool _CameraUsesNearClipPlane() { return ThisActor->CameraUsesNearClipPlane(); }
		bool CameraUsesNearClipPlane();
		static bool _CameraUsesFarClipPlane() { return ThisActor->CameraUsesFarClipPlane(); }
		bool CameraUsesFarClipPlane();


		Tools_Cutscene_Attachment* CreateAttachmentOfType( int iType );


};

class Tools_ChooseEntityToReplace : public Tools_ChooseObject
{
public :
	Tools_ChooseEntityToReplace(Tools_CutsceneActor_Object* pxActorObject){m_pxActorObject = pxActorObject;}

	virtual bool CanBeSelected(Tools_Object* pxObject);
	virtual void ObjectSelected(Tools_Object* pxObject);
	virtual void OnFinish(){m_pxActorObject->m_pxChooseObject = 0;delete this;}

	Tools_CutsceneActor_Object* m_pxActorObject;
};


//////////////////////////////////////////////////////////////////////////////////////////////////
/*---------------**
** Cutscene Undo **
**---------------*/

class CutsceneUndoData_Actor_Created : public RootUndoData
{
public :
	CutsceneUndoData_Actor_Created(Tools_CutsceneActor_Object* actorObject);
	virtual RootUndoData* ProcessUndoData();

	virtual int GetPriority() const;

	Asura_String ActorName;
};

class CutsceneUndoData_Actor_Destroyed : public RootUndoData
{
public :	
	CutsceneUndoData_Actor_Destroyed(Tools_CutsceneActor_Object* actorObject);
	virtual RootUndoData* ProcessUndoData();

	virtual int GetPriority() const;


	virtual void CopyToActor(Tools_CutsceneActor_Object* actorObject);

	int Type;
	Asura_String ActorName;
	Asura_String m_axSkinName[ASURA_ANIMATION_SKIN_COUNT];
	Asura_String InitialAnimationName;
	Asura_String m_axSkinFileName[ASURA_ANIMATION_SKIN_COUNT];
	Asura_String AnimationFileName;
	Asura_String m_xTargetName;
	int m_iAnimationFlags;
	float m_fAnimationDelay;
	u_int m_uActorFlags;
	u_int m_uShapeFlags;
	u_int m_uHierarchyFlags;
	Asura_Hash_ID m_uTextureHash;
	Asura_Hash_ID m_uIKTemplateID;
	#ifdef ASURA_USE_FACIAL_ANIMATION_SYSTEM
	Asura_Hash_ID m_uFaceID;
	#endif

	Asura_Hash_ID m_uShapeID;

	u_int m_uCameraFlags;
	Asura_Angle m_fInitialFOV;
	float m_fNearClip;
	float m_fFarClip;
	Asura_Cutscene_Camera_Shake m_xCameraShake;

	Asura_Vector_3 Position;
	Asura_Matrix_3x3 Orientation;

	Asura_Guid m_uGuid;
	Asura_Guid m_uGuidToReplace;
};

class CutsceneUndoData_Actor_Changed : public RootUndoData
{
public :	
	CutsceneUndoData_Actor_Changed(Tools_CutsceneActor_Object* actorObject);
	virtual RootUndoData* ProcessUndoData();
	virtual void SwapWithActor(Tools_CutsceneActor_Object* actorObject);

	virtual int GetPriority() const;

	Asura_String ActorName;
	Asura_String m_axSkinName[ASURA_ANIMATION_SKIN_COUNT];
	Asura_String InitialAnimationName;
	Asura_String m_axSkinFileName[ASURA_ANIMATION_SKIN_COUNT];
	Asura_String AnimationFileName;
	Asura_String m_xTargetName;
	int m_iAnimationFlags;
	float m_fAnimationDelay;
	u_int m_uActorFlags;
	u_int m_uShapeFlags;
	u_int m_uHierarchyFlags;
	Asura_Hash_ID m_uTextureHash;
	Asura_Hash_ID m_uIKTemplateID;
	#ifdef ASURA_USE_FACIAL_ANIMATION_SYSTEM
	Asura_Hash_ID m_uFaceID;
	#endif


	Asura_Hash_ID m_uShapeID;

	u_int m_uCameraFlags;
	Asura_Angle m_fInitialFOV;
	float m_fNearClip;
	float m_fFarClip;
	Asura_Cutscene_Camera_Shake m_xCameraShake;

	Asura_Guid m_uGuidToReplace;
};

class CutsceneUndoData_Actor_Rename : public RootUndoData
{
public :	
	CutsceneUndoData_Actor_Rename(class Tools_CutsceneActor_Object* actorObject,const class Asura_String& newName);
	virtual RootUndoData* ProcessUndoData();

	virtual int GetPriority() const;

	Asura_String ActorName;
	Asura_String OldName;
};

#endif //_TOOLS_CUTSCENEACTOR_OBJECT_H_
