// Asura_WAVAlign_Dialog.h
// Thomas Young - 18.08.08
// Copyright (C) 2008 Rebellion, All Rights Reserved.

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif

#ifndef __ASURA_WAV_ALIGN_DIALOG_H__
#define __ASURA_WAV_ALIGN_DIALOG_H__

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura_List.h"
#include "Core/Asura_Multithread.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Gadget.h"
#include "Interface/Asura_Overlay_System.h"
#include "Rendering/Asura_Text_Output.h"

#include "Misc/Tools_Dialog.h"

// D E F I N E S /////////////////////////////////////////////////////////////

#define ASURA_WAVALIGN_DIALOG_DEFAULT_WIDTH		256.0f
#define ASURA_WAVALIGN_DIALOG_DEFAULT_HEIGHT	96.0f

#define ASURA_WAVALIGN_RENDER_PLAYBACK_MARKER	0x00000001
#define ASURA_WAVALIGN_RENDER_LOOP_MARKERS		0x00000010
#define ASURA_WAVALIGN_RENDER_XAXIS				0x00000100

// E X T E R N A L S /////////////////////////////////////////////////////////

extern unsigned int Asura_OverlayBrightness;

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class Asura_WAVRender_Gadget;

// F U N C T I O N   D E F I N I T I O N S ///////////////////////////////////

class Asura_WAVAlign_Dialog : public Asura_Dialog
{
	public:
		
		Asura_WAVAlign_Dialog			( const Asura_Vector_2& xOffset, const float uWidth = ASURA_WAVALIGN_DIALOG_DEFAULT_WIDTH, const float uWAVHeight = ASURA_WAVALIGN_DIALOG_DEFAULT_HEIGHT, bool* pbModified = 0 );
		virtual ~Asura_WAVAlign_Dialog	();
		
		void	PerFrameUpdate();

		void	AddWAVEntry				( int iHandle = 0 );
		void	RemoveWAVEntry			( int iHandle = 0 );
		bool	LoadWAV					( const char* const szFilename, int iHandle = 0 );
		void	ClearWAV				( int iHandle = 0 );
		int		GetNumWAVEntries		();

		void	SetBarDuration			( float fDuration );
		float	GetBarDuration			()												{ return m_fBarDuration;			}

		void	Render					( const Asura_Vector_2& xOrigin );
		void	Update					( const Asura_Vector_2& xOrigin );

		float	GetTrackDuration		();

		float	GetIntroMarkerTime		()												{ return m_fIntroMarkerTime;		}
		float	GetOutroMarkerTime		()												{ return m_fOutroMarkerTime;		}

		void	SetIntroMarkerTime		( const float fTime )							{ m_fIntroMarkerTime = fTime;		}
		void	SetOutroMarkerTime		( const float fTime )							{ m_fOutroMarkerTime = fTime;		}

		void	SetPlaybackMarkerTime	( const float fTime )							{ m_fPlaybackMarkerTime = fTime;	}
		void	ClearPlaybackMarker		()												{ m_fPlaybackMarkerTime = 0;		}

		void	SetRenderFlags			( const u_int uFlags )							{ m_uRenderFlags = uFlags;			}
		void	SetRenderFlag			( const u_int uFlag, const bool bSet = true );

		bool	NoWAVsLoaded			();
		bool	AnyWAVsLoaded			()												{ return !NoWAVsLoaded();			}

	protected:
		
		virtual void ShowHelpText();

	private:
		
		Asura_WAVRender_Gadget* FindWAVRenderGadget ( int iHandle );

		float RoundTimeToBars ( float fTime );

		void UpdateVisibleTimeText ();

		u_int ScaleOpacity( const u_int uBaseColour, const float fRelativeOpacity );

		float m_fWidth;
		float m_fWAVHeight;

		float m_fVisibleTimeStart;
		float m_fVisibleTimeEnd;

		float m_fIntroMarkerTime;
		float m_fOutroMarkerTime;
		bool m_bIntroMarkerHighlighted;
		bool m_bOutroMarkerHighlighted;

		float m_fPlaybackMarkerTime;

		float m_fBarDuration;
		float m_fTicksHighlight;
		bool m_bShowBarsOnXAxis;
		bool m_bCanShowBarsOnXAxis;

		Asura_List<Asura_WAVRender_Gadget> m_xWAVRenderList;

		u_int	m_uDragState;

		bool*	m_pbModified;

		u_int	m_uRenderFlags;
};


class Asura_WAVRender_Gadget : public Asura_Gadget
{
	//This gadget is for rendering a waveform

	public:

		Asura_WAVRender_Gadget	( const int iHandle, const Asura_Vector_2 xOffset, float fWidth, float fHeight );
		~Asura_WAVRender_Gadget	();

		bool	LoadFromWAV		( const char* const pxWavFilename );
		void	ClearWAV		();

		void	Render			( const Asura_Vector_2& xOrigin );
		void	Update			( const Asura_Vector_2& xOrigin );
		
		void	SetVisibleTime	(float fStart, float fEnd);

		float	GetDuration		()	{ return m_fDuration;					}
		u_int	GetSamples		()	{ return m_uSamples;					}

		int		GetHandle		()	{ return m_iHandle;						}

		bool	HasWAV			()	{ return m_bHasLoadedWAV;				}

		bool	IsStillLoading	()	{ return !m_bFinishedLoadingSamples;	}
		void	AbortLoading	()	{ m_bAbortLoading = true;				}

	private :

				void WaitUntilSafe				();

				bool RecalculateSamples			();
				bool PrepareToReadSampleData	();
		static	void ThreadFuncLoadSamples		( const void* pData );
				
		float					m_fDuration;
		u_int					m_uSamples;

		float					m_fVisibleStart;
		float					m_fVisibleEnd;

		Asura_String			m_xWavFilename;
		Asura_WAVAlign_Dialog*	m_pxParent;
		int						m_iHandle;

		bool					m_bHasLoadedWAV;

		float					m_fWidthUnscaled;
		float					m_fHeightUnscaled;

		float*					m_afRenderSamplesAlpha;
		int						m_iThreadedReadProgress;
		int						m_iNumRenderSamples;

		static Asura_Mutex		m_xGadgetLoadFlagMutex;
		static volatile bool	m_bAnyGadgetIsLoading;

		volatile bool			m_bAbortLoading;
		volatile bool			m_bFinishedLoadingSamples;
		Asura_Mutex				m_xRenderSamplesMutex;
		//The following are mutex protected
		float*					m_afHighRenderSamples;
		float*					m_afLowRenderSamples;

};


#endif//__ASURA_WAV_ALIGN_DIALOG_H__
