// ------------------------------------------------------------------------------------ //
//																						//
// Asura_GUIMenu_Element_FMV.h															//
//																						//
// Created by Martin Hutchings - 24/03/2009												//
//																						//
// Copyright (C) 2009 Rebellion, All Rights Reserved.									//
//																						//
// ------------------------------------------------------------------------------------ //

#ifndef __ASURA_GUIMENU_ELEMENT_FMV_H__
#define __ASURA_GUIMENU_ELEMENT_FMV_H__

#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#ifdef ASURA_USE_GUI_MENU_SYSTEM
#include "Asura_GUIMenu_Element_Image.h"

#ifdef ASURA_USE_VIDEO_TO_TEXTURE_SYSTEM
#include "FMV/Asura_VideoToTexture.h" // for Asura_VideoToTexture::ASURA_FMV_FLAGS

#define ASURA_GUIMENU_SUPPORT_FMV_ELEMENTS		1
#endif

// -- Typedef -------------------------------------------------------------------------

// -- Enums ---------------------------------------------------------------------------

// -- Defines -------------------------------------------------------------------------

// -- Data Chunk Version --
// Versions: ASURA_CHUNK_ELEMENT_FMV_VERSION
// 0:	Initial data
#define ASURA_CHUNK_ELEMENT_FMV_VERSION 0

// ------------------------------------------------------------------------------------
//
// Asura_GUIMenu_FMV_System
// 
// System class for registering FMV's that can be played by the					
// Asura_GUIMenu_Element_FMV class.														
//
// ------------------------------------------------------------------------------------

class Asura_GUIMenu_FMV_System
{
public:

	enum GUIMENU_FMV_HANDLE
	{
		GUIMENU_FMV_HANDLE_NONE	= -1,
	};

	static void Initialise(void);
	static void Reset(void);
	// Shutdown the system. Stop all FMV's playing and clean up all FMV objects
	static void Shutdown(void);
	// Update the FMV system to make sure FMVs are playing.
	static void Update(void);

	// Register an FMV with the system. A unique FMV is identified using
	// its name, the texture it will render to while playing, if the sound is enabled,
	// the sound track it plays and if the FMV loops.
	// Each unique FMV is assigned a handle returned from this function.
	// If a duplicate FMV is registered than the handle to the existing FMV is returned.
	// Each time an FMV is registered the handle has its reference count increased.
	// Every call to RegisterFMV must match with a call to DeregisterFMV.
	// When the FMV is no longer needed its is destroyed.

	// An FMV with the same name can be registered again if for example the texture index
	// was different. This allows the same FMV to be played to two different textures. This also
	// includes playing different sound tracks.
	static Asura_Handle RegisterFMV(Asura_String xFilename,
									int iTextureRTIndex, 
									u_int uSoundTrackIndex,
									bool bPlaySound,
									bool bLoop);

	// Call to show the system is no longer interested in the FMV represent by the handle.
	// If the reference count on the FMV reaches 0 then the FMV object is destroyed.
	static void DeregisterFMV(Asura_Handle& iHandle);

	// Is the FMV currently playing.
	static bool IsPlaying(Asura_Handle iHandle);

	// Cause the FMV to start playing. If the FMV is already playing then it continues to play from where it is.
	// This call increases the play reference count. A matching call to stop should be made for each call to Play, 
	// but is not esscential as the system will stop any FMV's playing that haven't received a HeartBeat (See below).
	// If the FMV isn't playing the a new VideoToTexture object is created, which creates the streaming buffers and
	// the texture for the FMV.
	static bool Play(Asura_Handle iHandle);

	// Tell the FMV to stop playing. This decrements the Play count. If the play count reaches 0 then the FMV is stopped,
	// otherwise it will continue to play as something else has also called the Play function.
	// Once the FMV is stopped the VideoToTexture object, along with the streaming buffers and texture are destroyed.
	static void Stop(Asura_Handle iHandle);


	// Check that the handle is still valid. If the handle isn't valid then the FMV is no longer register with the system.
	static bool ValidateHandle(Asura_Handle& iHandle);

	// Keep the FMV playing. If the FMV is playing and hasn't been pulsed within the last few frames then
	// it is automatically stopped by the system. This in turn will destroy the VideoToTexture object 
	// if nothing else is playing the movie.
	// This prevents the GUIMenu system from playing movies that aren't been used. i.e. Rendered. 
	static void HeartBeat(Asura_Handle iHandle);

#ifdef ASURA_USE_VIDEO_TO_TEXTURE_SYSTEM
	// Get the VideoToTexture object. If the FMV hasn't been opened then this will be NULL.
	// This also cause a heartbeat so the VideoToTexture object doesn't get destroyed.
	// Don't keep the pointer returned from the function. Only use locally. The object
	// maybe destroyed without notice.
	static Asura_VideoToTexture* GetVideoToTexture(Asura_Handle iHandle);
#endif

	// Stop all FMV's from playing irrespective of their play count and free up all the memory used by the
	// VideoToTexture objects.
	static void StopAllForced();

	static void DebugOutput();

private:

	class Asura_GUIMenu_FMV
	{
	public:
#ifdef ASURA_USE_VIDEO_TO_TEXTURE_SYSTEM
		Asura_VideoToTexture* m_pxVideoToTexture;	// Only for movies that are currently playing. Holds the stream buffers and texture.
		Asura_VideoToTexture::ASURA_FMV_FLAGS m_eFlags;	// Flags to enable/disable sound and looping.
#endif		
		int m_iTextureRTIndex;					    // Texture index to render the FMV to.
		Asura_Hash_ID m_uFilenameHash;				// Hash of the filename.
		Asura_String m_xFilename;					// Filename of the FMV.
		u_int m_uSoundTrackIndex;					// The sound track index to play

		Asura_Handle m_iHandle;							// The handle used to reference the instance of this class.
		int m_iRegisterCount;							// The number of times this FMV data has been registered with the system.
		int m_iPlayCount;								// The number of calls made to Play() this FMV.
		u_int m_uHeartBeatFrameNum;							// The last frame the system was told this FMV need to continue to Play.
	};

	// Find the FMV object given a handle.
	static Asura_GUIMenu_FMV* FindFMV(Asura_Handle iHandle);
	// Delete the FMV object given a handle.
	static void DeleteFMV(Asura_Handle iHandle);

	static Asura_LinkList<Asura_GUIMenu_FMV*> s_xRegisteredFMV;	// List of unique FMV's and settings.
	static Asura_Handle s_iNextHandle;							// The next handle to allocate

	static u_int s_uNumMoviesPlaying;
};


// -- Structures ----------------------------------------------------------------------
class Asura_GUIMenu_Element_FMV : public Asura_GUIMenu_Element_Image
{
	typedef Asura_GUIMenu_Element_Image PARENT;

public:

	Asura_GUIMenu_Element_FMV( void);
	virtual ~Asura_GUIMenu_Element_FMV( void);

	virtual void 				Render( u_int uState);
	virtual void				Render( u_int uState, const Asura_Bounding_Rectangle& xBounds);
	virtual void				Copy( const Asura_GUIMenu_Root* pxSource );

	virtual void				Update( float fElapsedTime);

#ifdef ASURA_TOOLS
	bool						IsFMVValid();

	virtual void				UpdateLocalDataFromStyle( void);

	virtual void				WriteToChunkStream( Asura_Chunk_Stream& xStream) const;
	virtual void				ExportToXML(Tools_GUIMenu_XMLExporter* pxExporter) const;
#endif // ASURA_TOOLS

	virtual void				ReadFromChunkStream( Asura_Chunk_Stream& xStream, Asura_GUIMenu_Root* pxParentObject, u_int uChunkVersion);

	void SetFMVFilename(Asura_String xFilename);
	Asura_String GetFMVFilename() { return m_xFMVName; }

	void Play();
	void Stop();

	void RegisterFMV();

	void SetLoop(bool bLoop) { m_bLoop = bLoop; }
	bool GetLoop() { return m_bLoop; }

	void SetPlaySound(bool bPlaySound) { m_bPlaySound = bPlaySound; }
	bool GetPlaySound() { return m_bPlaySound; }

	void SetSoundTrackIndex(u_int uSoundTrackIndex) { m_uSoundTrackIndex = uSoundTrackIndex; }
	u_int GetSoundTrackIndex() { return m_uSoundTrackIndex; }

protected:
	
private:

	// -- Variables -------------------------------------------------------------------
	Asura_String m_xFMVName;
	u_int m_uSoundTrackIndex;
	bool m_bPlaySound;
	bool m_bLoop;

public:

protected:

private:

	//Asura_VideoToTexture* m_pxVideoToTexture;
	Asura_Handle m_iHandle;

	bool m_bPlaying;
	// --------------------------------------------------------------------------------
};
#endif // ASURA_USE_GUI_MENU_SYSTEM
#endif // __ASURA_GUIMENU_ELEMENT_FMV_H__
