//
// Asura_StreamingBackgroundSound_System.h
//
// Created by Richard Rice - 08/01/04
// 
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __ASURA_STREAMINGBACKGROUNDSOUND_SYSTEM_H__
#define __ASURA_STREAMINGBACKGROUNDSOUND_SYSTEM_H__

#include "Core/Asura_Maths.h"
#include "Core/Asura_String.h"
#include "Core/Asura_Hash.h"
#include "Network/Asura_Guid.h"


class Asura_AABB_Tree;
class Asura_Message;
class Asura_VolumeGroup;

#define ASURA_STREAMINGBACKGROUNDSOUNDFLAG_ACTIVE 0x00000001
#define ASURA_OLDSTREAMINGBACKGROUNDSOUNDFLAG_SPHERE 0x00000002	//obsolete
#define ASURA_STREAMINGBACKGROUNDSOUNDFLAG_USECLIPVOLUME 0x00000004
#define ASURA_STREAMINGBACKGROUNDSOUNDFLAG_INVERTCLIPVOLUME 0x00000008

enum
{
	ASURA_STREAMINGBACKGROUNDSOUNDTYPE_CUBOID = 0,
	ASURA_STREAMINGBACKGROUNDSOUNDTYPE_SPHERE = 1,
	ASURA_STREAMINGBACKGROUNDSOUNDTYPE_CYLINDER = 2,
};

class Asura_StreamingBackgroundSound
{
public :
	void Initialise();
	void Shutdown();

	float GetVolumeWeighting(const Asura_Vector_3& xPosition) const;//get the volume multiplier based on where position is relative to inner and outer box

	#ifdef ASURA_TOOLS
	bool IsMemberOfCurrentLightSet() const;
	bool IsMemberOfTemplateInstance() const {return m_uTemplateGuid != ASURA_GUID_UNREGISTERED;}

	//Used after a phonon has been created from the template's chunk buffers to adjust positions etc
	//as needed. RAR 27/04/2008
	void ApplyChangesForTemplateInstance(class Tools_EntityTemplateInstance* pxInstance);
	#endif


	bool IsActive() const {return (m_uFlags & ASURA_STREAMINGBACKGROUNDSOUNDFLAG_ACTIVE) ? true : false;}
	bool IsSphere() const {return (m_iType == ASURA_STREAMINGBACKGROUNDSOUNDTYPE_SPHERE);}
	bool IsCylinder() const {return (m_iType == ASURA_STREAMINGBACKGROUNDSOUNDTYPE_CYLINDER);}

	bool Contains(const Asura_Vector_3& xPos) const;

	////////////////////////////////

	Asura_String m_xFilename;//filename of streaming sound to play
	Asura_Hash_ID m_uFilenameHash;

	float m_fVolume;//volume multiplier

	int m_iType;//cuboid/sphere/cylinder

	Asura_Bounding_Box m_xInnerBox;//area in which sound is at full volume
	Asura_Bounding_Box m_xOuterBox;//area in which sound is audible at all

	Asura_Quat m_xOrient;//orientation for both inner and outer bounding box (if used , BB+orient behaves like Asura_OrientedVolume)

	//For spherical and cylinder sound volumes :
	float m_fInnerRadius;
	float m_fOuterRadius;
	Asura_Vector_3 m_xPosition;

	//For cylinders :
	float m_fInnerHeight;
	float m_fOuterHeight;

	Asura_Hash_ID m_uMixer;//Sound event system mixer to use.

	#ifdef ASURA_TOOLS
	u_int m_uLightSets;//bitfield of of the increasingly inappropriately named lightsets that this is included in
	Asura_Guid m_uTemplateGuid;//guid of the template instance that this belongs to
	int m_iTemplateVersion; //last known version of the template that this belongs to
	#endif

	u_int m_uFlags;
	int m_iPriority;

	Asura_VolumeGroup* m_pxClipVolume;//optional volumes to clip sound to

	u_int m_uID;//Unique ID to help with linking up to static messages
	Asura_Guid m_uGuid;//guid of controller entity
};

class Asura_DefaultStreamingBackgroundSound
{
public :
	void Initialise()
	{
		m_xFilename.MakeNull();

		m_uFilenameHash = 0;
		m_fVolume = 1.0f;
		m_uMixer = 0;
	}

	

	Asura_String m_xFilename;//filename of streaming sound to play
	Asura_Hash_ID m_uFilenameHash;
	float m_fVolume;
	Asura_Hash_ID m_uMixer;//Sound event system mixer to use.
	
};


//System for managing background streaming sounds.
//The sounds have volumes indicating when they should be played , but aren't played
//as if they come from any particular point.

#define ASURA_STREAMINGSOUNDSYSTEMFLAG_STOPDURINGMUSIC		0x00000001
#define ASURA_STREAMINGSOUNDSYSTEMFLAG_DEFAULTPERLIGHTSET	0x00000002 //If set then there is one default sound per light set

class Asura_StreamingBackgroundSound_System
{
public :
	static void Initialise();
	static void Shutdown();
	static void Reset();

	static void Update();

	static int GetNumberOfSounds() {return s_iNumberOfSounds;}
	
	static Asura_StreamingBackgroundSound* GetSound(int iIndex){return &s_pxSounds[iIndex];}
	static Asura_StreamingBackgroundSound* GetSoundByID(u_int m_uID);
	
	#ifdef ASURA_TOOLS
	static int CreateSound(const Asura_Vector_3& xPosition, u_int uID = 0);
	static void DeleteSound(int iIndex);
	static int GetSoundIndexFromID(u_int uID);
	static Asura_StreamingBackgroundSound* GetSoundFromID(u_int uID);
	static void UpdateVolumeTree();
	static void InvalidateVolumeTree();
	#endif

	static void StopAll();

	static bool ShouldStopDuringMusic(){return (s_uFlags & ASURA_STREAMINGSOUNDSYSTEMFLAG_STOPDURINGMUSIC)!=0;}

	//called by music system to tell this system that music is about to start (and
	//so it should probably be stopping sounds to release sound handles).
	static void NotifyMusicStarting(bool bCrossFade);

	static void Pause();//(MKR - 29.08.06)
	static void Unpause();//(MKR - 29.08.06)

	static float GetVolume() { return GetDefaultSound()->m_fVolume; }//MKR 04/09/06
	static void SetVolume(const float fVolume) { GetDefaultSound()->m_fVolume = fVolume; }//MKR 04/09/06

	#ifdef ASURA_TOOLS
	static void SetDisabled(bool bSet);
	#endif

	//Get the default sound (for the current light set in tools)
	#ifdef ASURA_TOOLS
	static Asura_DefaultStreamingBackgroundSound* GetDefaultSound();
	static Asura_DefaultStreamingBackgroundSound* GetDefaultSound(u_int uLightSets, bool bCreate = true);
	#else
	static Asura_DefaultStreamingBackgroundSound* GetDefaultSound(){return &s_xDefaultSound;}
	#endif
	static bool HasDefaultPerLightSet(){return (s_uFlags & ASURA_STREAMINGSOUNDSYSTEMFLAG_DEFAULTPERLIGHTSET)!=0;}

	static int GenerateID() {return s_uNextID++;}

	static void HandleMessage(const Asura_Message* pxMessage);

	static float GetMixerVolume(int iIndex);

	//Gets the file to play ,possibly modified by platform
	static const char* GetSoundFilenameToPlay(int iIndex);

#ifdef ASURA_USE_DEBUGOVERLAY
	static void DoStreamingBackgroundSoundDebugOverlay ( void* const pxIgnore );
#endif

private :
	static void TestVolumeTree();
	static bool VolumeTreeCallback(u_short usIndex);

	//Adds to the list of active sounds if there is room
	static void AddToActiveSounds(int iSoundIndex, int iSortOrder);

	//starts/stops sounds based on the sound handles available
	static void UpdatePlayingStatus();

	#ifdef ASURA_TOOLS
	static bool FillVolumeTreeCallback(u_int uNumObjects,Asura_Bounding_Box* pxBoxes,Asura_Vector_3* pxCentres);
	#endif

	//determines which sound has higher priority
	static int ComparePriorityAndWeight(int iPriority1, float fWeight1, int iPriority2, float fWeight2);

	//check if there is music playing
	static bool IsMusicPlaying ();

	//default background sound to play if in no volume (or to mix in if in one volume)
	#ifdef ASURA_TOOLS
	//default sounds to use for each light set combination
	static Asura_TemplateHashTree<Asura_DefaultStreamingBackgroundSound> s_xDefaultSoundTree;
	#else
	static Asura_DefaultStreamingBackgroundSound s_xDefaultSound;
	#endif

	//Number of background sound volumes
	static int s_iNumberOfSounds;
	//array of background sounds
	static Asura_StreamingBackgroundSound* s_pxSounds;

	//tree of outer volumes for sounds
	static Asura_AABB_Tree* s_pxVolumeTree;

	static u_int s_uFlags;


	static float s_fFadeTimer;//global fade out timer
	static bool s_bFadeOut;

	#ifdef ASURA_TOOLS
	static bool s_bDisabled;
	#endif

	static u_int s_uNextID;


	friend class Asura_Chunk_StreamingBackgroundSound;
	friend class Asura_Chunk_StreamingBackgroundSound_InGame;
	friend class Tools_StreamingBackgroundSound_Object;
	friend class Tools_Mode_Sound;

};





#endif //__ASURA_STREAMINGBACKGROUNDSOUND_SYSTEM_H__
