#ifndef SOUNDENGINE_H
#define SOUNDENGINE_H

#include "MusicManager.h"
#include "SoundManager.h"

#include <map>
#include <string>
using namespace std;



namespace SoundSystem
{
	
	// forward declaration
	class MusicManager;

	class SoundManager;
	/**
	 * La classe de gestion de l'API de son.
	 *
	 * Cette classe a en charge la creation du context de son, et des managers de son et de musique.
	 * Elle utilise les patterns Singleton et Factory afin de crée les SoundManager et MusicManager.
	 * En effet, il faut que le Sound engine puisse nettoyer les stream crée par FMOD car ils ne sont pas nettoyé 
	 * automatiquement a la fermeture de FMOD.
	 */
	class SoundEngine
	{
	private:

		static SoundEngine * instance;
		/**
		 * La map contenant l'ensemble des musicManager crée par le SoundEngine.
		 */
		map<void*,MusicManager*> * musicManagers;

		/**
		 * La map contenant l'ensemble des soundManager crée par le SoundEngine.
		 */
		map<void*,SoundManager*> * soundManagers;

		/**
		 * constructeur privé pour le pattern singleton
		 */
		SoundEngine(void);

		/**
		 * destructeur privé pour le pattern singleton
		 */
		~SoundEngine(void);

		/**
		 * le volume principal du son.
		 */
		int masterVolume;
	protected:
	public:
		/**
		 * methode retournant l'instance unique de SoundEngine
		 * @return SoundEngine : l'instance unique de SoundEngine.
		 */
		static SoundEngine &getInstance();

		/**
		 * methode permettant de detruire l'instance unique de SoundEngine
		 */
		static void destroy();

		/**
		 * Methode creant un nouveau MusicManager.
		 *
		 * Cette methode crée un nouveau MusicManager qui doit etre liberer en appelant la methode freeMusicManager().
		 *
		 * @return MusicManager* : Pointeur sur le nouveau MusicManager.
		 */
		MusicManager * createMusicManager();

		/**
		 * detruit un musicManager crée par la methode createMusicManager().
		 *
		 * @param manager : pointeur sur le MusicManager a detruire
		 */
		void freeMusicManager(MusicManager * manager);

		/**
		 * Methode creant un nouveau SoundManager.
		 *
		 * Cette methode crée un nouveau SoundManager qui doit etre liberer en appelant la methode freeSoundManager().
		 *
		 * @return SoundManager* : Pointeur sur le nouveau SoundManager.
		 */
		SoundManager * createSoundManager();

		/**
		 * detruit un SoundManager crée par la methode createSoundManager().
		 *
		 * @param manager : pointeur sur le SoundManager a detruire
		 */
		void freeSoundManager(SoundManager * manager);

		/**
		 * demarre la gestion du son.
		 *
		 * @param frequence : la frequence de fonctionnement du son en Hz. generalement mis a 44100hz
		 * @param channels : le nombre de channels desiré par l'utilisateur. ce nombre de channels est
		 * le nombre de channels software et ne prend pas en compte les channels hardware qui eux sont dependants
		 * de la carte son.
		 * @param foregroundApp : Si ce parametre est mis a true, avec le parametre driver mis a DSOUND, le manager
		 * essaye de lier le context sonore a la fenetre de fond, ainsi, si la fenetre perd le focus, le son se met 
		 * en pause. TODO : tester si ceci marche réelement, il semble que ca ne fontionne par merveilleusement bien ;-)
		 * @param driver : le nom du driver de son a utiliser. Par defaut, dit a FMOD de choisir le driver par lui même
		 * mais l'utilisateur paut specifier un driver dans la liste suivante :
		 * - DSOUND : DirectSound
		 * - WINMM : Windows Media Manager
		 * - A3D : A3D
		 * - OSS : linux Open Sound System
		 * - ESD : linux Enlightment Sound Daemon
		 * - ALSA : linux ALSA
		 * - ASIO : Low latency ASIO driver 
		 * - NOSOUND : pas de son, le manager de son fonctionne normalement mais ne generera pas de sons.
		 */
		void start(int frequence,int channels,bool foregroundApp = false,string driver = "");

		/**
		 * stop le fonctionnement du SoundEngine.
		 *
		 * Afin d'eviter des problemes lié a la fermeture des stream de FMOD, cette methode stop aussi tout les
		 * SoundManager et MusicManager.
		 */
		void stop();

		/**
		 * definit le volume principal de l'application. Chaque son sera modulé par ce volume.
		 *
		 * @param volume : le volume principale de l'application, doit etre comprit entre 0 et 255
		 */
		void setMasterVolume(int volume);

		/**
		 * retourne le volume principal de l'application.
		 *
		 * @return int : le volume principale de l'application.
		 */
		int getMasterVolume();

		/**
		 * methode pemettant de savoir si l'API peut jouer un son ou pas.
		 *
		 * Typiquement, si l'API ne peut pas jouer un son, c'est probablement que tout les channels alloué
		 * sont utilisé.
		 *
		 * @return bool : true si l'API peut jouer un son, false sinon.
		 */
		bool canPlaySound();

		/**
		 * methode a appeler obligatoirement pour mettre a jour la position de la camera pour la gestion du son.
		 *
		 * @param x : La position X de la camera
		 * @param y : La position Y de la camera
		 * @param z : La position Z de la camera
		 * @param dx : La composante X du vecteur de direction de la camera
		 * @param dy : La composante Y du vecteur de direction de la camera
		 * @param dz : La composante Z du vecteur de direction de la camera
		 */
		void update(float x, float y, float z, float dx, float dy, float dz);
	};
}// namespace SoundSystem


#endif
