#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef _TOOLS_MODE_CUTSCENE_H_
#define _TOOLS_MODE_CUTSCENE_H_

#include "Core/Asura_Handle.h"
#include "Core/Asura_Maths.h"

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

class Tools_Cutscene_Object;
class Asura_Cutscene;
class Asura_Cutscene_Event;
struct Asura_FMVSubtitle;
class Asura_SaveBlock;
class Asura_String;
struct Tools_IniFile;

enum CutsceneTimerMode
{
	CUTSCENETIMER_SECONDS,CUTSCENETIMER_25FPS,CUTSCENETIMER_30FPS
};

class Tools_Mode_Cutscene : public Tools_Mode
{
	public :
		Tools_Mode_Cutscene()
		{
			s_pxThis = this;
		}
		~Tools_Mode_Cutscene()
		{
			s_pxThis = NULL;
		}

		void InitialiseMode(void);

		void Update(void);
		void RenderUI(void);
		void EarlyRender(void);
		
		void ShutdownMode(void);

		virtual void QuickSave(void);

 		bool IsModified();

		virtual void EditCutscene(class Tools_Cutscene_Object*);


		//virtual functions for dealing with project specific cutscene types
		virtual int SelectCutsceneType();
		virtual Asura_Cutscene* AllocateCutscene(Asura_String& name,int cutsceneType);
		virtual Tools_Cutscene_Object* CreateCutsceneObject(Asura_Cutscene* cutscene);

		virtual class CutsceneModeUndo* AllocateCutsceneModeUndo();

		//checks the object type to see if it is a cutscene object type
		virtual bool IsCutsceneObject(int type){return type==TOT_Cutscene;}

		//Used by GF2 to match up camera positions between transitions/scenes
		virtual void UpdateLinkedCutscenes(){};
        
        //Used by GF2 to fill in any important blanks with default settings e.g. death anims
        virtual void FillInAnyMissingData(){};

		//Used to set default values in a newly created cutscene.
		virtual void SetCutsceneDefaults(Asura_Cutscene* pxCutscene);

		//Determines whether WriteFMVSubtitlesFromTextFile() should check the dialogue system for text.
		//If this is used then a file will be created per language for each fmv
		virtual bool ShouldGetFMVSubtitleTextFromDialogueLines() const {return false;}
		

		static CutsceneTimerMode GetTimerMode(){return s_eTimerMode;}
		static float ConvertSecondsToDisplayedTime(float fValue,int iMode = s_eTimerMode);
		static float ConvertDisplayedTimeToSeconds(float fValue,int iMode = s_eTimerMode);

		static bool IsPlayingCutscene(){return s_pxThis ? s_pxThis->CutscenePlayback_Active : false;}
		//checks if a cutscene is being played that has a camera , and the camera isn't disabled
		static bool IsControllingCamera();

		static Tools_Cutscene_Object* GetCurrentCutsceneObject(){return CurrentCutscene;}
		static Asura_Cutscene* GetCurrentCutscene();

		static bool GetDisablePFX(){return s_pxThis ? s_pxThis->m_bDisablePFX : false;}

		//Gets a list of all entities that are used as entity attachments in cutscenes
		static void ListGuidsUsedByEntityAttachments(List<Asura_Guid>& xAttachmentList);

	//private :
		//loads/saves data for this mode
		void TransferModeData(int mode);

		STATIC_VOID_FN(ToggleCutsceneModeOverlay);
		STATIC_BOOL_FN(CutsceneModeOverlayIsOn);
		void CreateCutsceneModeOverlay(void);
		virtual void AddCutsceneModeOverlayControls(class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset);

		STATIC_VOID_FN(ToggleCutsceneEditOverlay);
		STATIC_BOOL_FN(CutsceneEditOverlayIsOn);
		void CreateCutsceneEditOverlay(void);

		STATIC_VOID_FN(ToggleCutscenePlaybackOverlay);
		STATIC_BOOL_FN(CutscenePlaybackOverlayIsOn);
		void CreateCutscenePlaybackOverlay();
		void UpdateCutscenePlaybackOverlay();

		void HandleKeyboard();

		STATIC_VOID_FN(CreateCutscene);
		Tools_Cutscene_Object* CreateCutscene( const char* szName, int iType );
		STATIC_VOID_FN(ImportCutsceneFromTextFile);
		STATIC_VOID_FN(CopyCutscene);

		STATIC_VOID_FN(CreateActor);
		STATIC_VOID_FN(CopyActor);
		STATIC_VOID_FN(DuplicateSelectedActors);

		STATIC_VOID_FN(EditCutsceneDirectory);

		STATIC_VOID_FN(EditCutsceneName);

		STATIC_VOID_FN(CreateCutsceneEvent);
		STATIC_VOID_FN(EditEvent);


		STATIC_VOID_FN(RecordWavFile);
		STATIC_VOID_FN(PickWavFile);

		STATIC_VOID_FN(ExportCutscene);

		STATIC_VOID_FN(SetTimerMode);
	
		virtual void StartPlayback();
		virtual void StopPlayback();
		static void RefreshPlayback();
		void AdvanceCutsceneToTime(float time);
		void ShowTimeline();

		void UpdateSoundTrack(float fTolerance);

		//deals with resetting various SFX when cutscene is restarted
		void OnRestart();

		void ActivateParticleGenerators(bool bActive);

		STATIC_VOID_FN(CutscenePlayback_Rewind);
		STATIC_VOID_FN(CutscenePlayback_FrameBack);
		STATIC_VOID_FN(CutscenePlayback_Play);
		STATIC_VOID_FN(CutscenePlayback_Pause);
		STATIC_VOID_FN(CutscenePlayback_Stop);
		STATIC_VOID_FN(CutscenePlayback_FrameForward);
		STATIC_VOID_FN(CutscenePlayback_FastForward);

		STATIC_VOID_FN(ImportCutscene);
		
		STATIC_VOID_FN(ReloadAnimations);

		bool CutsceneIsPlaying(){return CutscenePlayback_Active;}

		virtual void UpdateObjectVisibilities();
//		void ShowEntitiesForMessageEditing(bool show);


		enum DialogID
		{
			DialogID_TimerMode,
		};

		STATIC_VOID_FN(RecordScreenshots);
		void BeginRecordScreenshots();
		void EndRecordScreenshots();

		static void DisablePFXClicked();

		void Verify(bool bAutomatic);

		void UpdateTimelineBar();

		static void CreateCutsceneReport();
		static void AddCutsceneReportEntry(const char* szName, const char* szFilename, const char* szCutscene, const char* szActor, bool bSkin);


										
		///////////////////////////
		//data
		Asura_Handle MenuHandle;

		Asura_Vector_2 CutsceneModeOverlayPosition;
		bool	CutsceneModeOverlayOpen;

		Asura_Vector_2 CutsceneEditOverlayPosition;
		bool CutsceneEditOverlayOpen;

		Asura_Vector_2 CutscenePlaybackOverlayPosition;
		bool CutscenePlaybackOverlayOpen;
		
		bool HideCutsceneObjects;
		bool HideEventObjects;
		bool m_bHideTrackObjects;
		bool m_bHideActorObjects;
		bool HideStaticObjects;
		bool m_bHideContainerObjects;
		bool m_bHideOtherEntities;
		bool m_bUseRecordedWavFile;
		bool m_bHighlightHierarchyActors;
		bool m_bDisablePFX;

		//cutscene playback data
		bool CutscenePlayback_Active;
		bool CutscenePlayback_HideObjects;
		bool CutscenePlayback_Refresh;
		bool CutscenePlayback_TimesliderModified;
		float CutscenePlayback_DeltaTime;
		float CutscenePlayback_Speed;
		float CutscenePlayback_Timer;


		float m_fScreenshotsFrameRate;
		bool m_bBeginScreenshotRecording;
		bool m_bRecordingScreenshots;

		static CutsceneTimerMode s_eTimerMode;

		static class Tools_Cutscene_Object* CurrentCutscene;
		static Tools_Mode_Cutscene* s_pxThis;//pointer to the mode for use by the static members

private:

		static void WriteFMVSubtitleFiles();
		static void WriteFMVSubtitles(const Asura_Cutscene* pxCutscene);
	
		static void WriteFMVSubtitlesFromTextFile();
        static void WriteFMVSubtitleTextPageChunk( int iLanguage, u_int uSubtitleCount,
                                                   const Asura_FMVSubtitle* pxSubtitles, const Asura_String* pxSubtitleStringIDs,
                                                   Asura_SaveBlock* pxSaveBlock );

		static void SendStaticMessage(const struct Asura_StaticMessage* pxMessage, Asura_Guid uFrom); 

		void ImportFromTextFile_Actor(Tools_IniFile& xIni, Asura_Cutscene* pxCutscene );
		void ImportFromTextFile_Camera(Tools_IniFile& xIni, Asura_Cutscene* pxCutscene);
		void ImportFromTextFile_Attachment(Tools_IniFile& xIni, Asura_Cutscene* pxCutscene);
		void ImportFromTextFile_Event(Tools_IniFile& xIni, Asura_Cutscene* pxCutscene);

		void ImportFromTextFile_Event_AnimationChange(Tools_IniFile& xIni, Asura_Cutscene* pxCutscene, Asura_Cutscene_Event* pxEvent);
		void ImportFromTextFile_Event_FieldOfView(Tools_IniFile& xIni, Asura_Cutscene* pxCutscene, Asura_Cutscene_Event* pxEvent);

		//Gets filename relative to asura_files. xFilename is non-const so that TidyFilename can be used on it
		const char* GetRelativeFilename(Asura_String& xFilename);
		
		//Reads in position/euler values from the current section of an ini file
		bool Get3dsMaxPositionFromTextFile(Tools_IniFile& xIni, const char* szID, Asura_Vector_3& xOutputPos);
		bool Get3dsMaxOrientationFromTextFile(Tools_IniFile& xIni, const char* szID, Asura_Matrix_3x3& xOutputMat);


};

//////////////////////////////////////////////////////////////////////////////////////////////////
/*---------------**
** Cutscene Undo **
**---------------*/
class CutsceneModeUndo : public VariableSizeUndo
{
public :
	CutsceneModeUndo()
	:VariableSizeUndo(10000){}

	virtual void PreUndoProcessing();
	virtual void PostUndoProcessing();


	void Log_TrackPoint_Created(class Tools_CutsceneTrackPoint_Object* pointObject);
	void Log_TrackPoint_Destroyed(class Tools_CutsceneTrackPoint_Object* pointObject);
	void Log_TrackPoint_Changed(class Tools_CutsceneTrackPoint_Object* pointObject);

	void Log_Track_Created(class Tools_Cutscene_Track* track);
	void Log_Track_Destroyed(class Tools_Cutscene_Track* track);
	void Log_Track_Rename(class Tools_Cutscene_Track* track);
	void Log_Track_Changed(class Tools_Cutscene_Track* track);

	void Log_Actor_Created(class Tools_CutsceneActor_Object* actorObject);
	void Log_Actor_Destroyed(class Tools_CutsceneActor_Object* actorObject);
	void Log_Actor_Changed(class Tools_CutsceneActor_Object* actorObject);
	void Log_Actor_Rename(class Tools_CutsceneActor_Object* actorObject,const class Asura_String& newName);

	void Log_Cutscene_Changed(Tools_Cutscene_Object* pxCutsceneObject);

	//overide to allocate appropriate undo data according to actor type
	virtual RootUndoData* CreateUndo_Actor_Created(class Tools_CutsceneActor_Object* actorObject);
	virtual RootUndoData* CreateUndo_Actor_Destroyed(class Tools_CutsceneActor_Object* actorObject);
	virtual RootUndoData* CreateUndo_Actor_Changed(class Tools_CutsceneActor_Object* actorObject);
	virtual RootUndoData* CreateUndo_Actor_Rename(class Tools_CutsceneActor_Object* actorObject,const class Asura_String& newName);

	void Log_Event_Created(class Tools_Cutscene_Event* event);
	void Log_Event_Destroyed(class Tools_Cutscene_Event* event);
	void Log_Event_Changed(class Tools_Cutscene_Event* event);

	//overide to allocate appropriate undo data according to event type
	virtual RootUndoData* CreateUndo_Event_Changed(class Tools_Cutscene_Event* event);

	//enumeration wheich defines which undo types have highest priority when
	//displaying the undo messages
	enum
	{
		PRIORITY_TRACKPOINT_CHANGED,
		PRIORITY_TRACKPOINT_DESTROYED,
		PRIORITY_TRACKPOINT_CREATED,

		PRIORITY_TRACK_CHANGED,
		PRIORITY_TRACK_RENAMED,
		PRIORITY_TRACK_DESTROYED,
		PRIORITY_TRACK_CREATED,

		PRIORITY_EVENT_CHANGED,
		PRIORITY_EVENT_DESTROYED,
		PRIORITY_EVENT_CREATED,

		PRIORITY_ACTOR_CHANGED,
		PRIORITY_ACTOR_RENAMED,
		PRIORITY_ACTOR_DESTROYED,
		PRIORITY_ACTOR_CREATED,
		
		PRIORITY_CUTSCENE_CHANGED,
 	};



};

extern CutsceneModeUndo* CutsceneUndo;

//used by undo for locating the actors/tracks/points
class Tools_Cutscene_Object* GetCutsceneObject( const char* szName);
class Tools_CutsceneActor_Object* GetActorObject(const class Asura_String& xActorName);
class Tools_Cutscene_Track* GetCutsceneTrack(const class Asura_String& xAtorName,int iTrackID);
class Tools_CutsceneTrackPoint_Object* GetTrackPointObject(const class Asura_String& xActorName,int iTrackID,int m_iPointID);
class Tools_Cutscene_Event* GetToolsCutsceneEvent(int id);




#endif // _TOOLS_MODE_CUTSCENE_H_

