#ifndef MUSICMANAGER_H
#define MUSICMANAGER_H

#include "fmod/fmod.h"
#include "fmod/wincompat.h"
#include <string>
#include <iostream>

#include "PlayList.h"
#include "SoundEngine.h"

using namespace std;

namespace SoundSystem
{
	/**
	 * La classe s'occupant de la gestion de la musique.
	 *
	 * Cette classe peut charger des playList, on peut lui ajouter des musiques, et elle gere la lecture des fichiers
	 * audios.
	 */
	class MusicManager
	{
		/**
		 * seul la classe SoundEngine peut crée et detruire des MusicManager.
		 */
		friend class SoundEngine;
	private:
		/**
		 * le stream sur lequel est lue la musique.
		 */
		FSOUND_STREAM * stream;
		/**
		 * le channel sur lequel est joué la musique
		 */
		int channel;

		/**
		 * le volume sonore de la musique
		 */
		int level;

		/**
		 * la playliste qui gere les fichier audio. Cette playlist a comme particularitée de ne contenire que des 
		 * fichier existant réelement sur le disque. Ainsi, on peut les lires en sachant qu'un fichier physique 
		 * existe bien.
		 */
		PlayList playList;

		/**
		 * booleen permettant de savoir si le manager est demarré ou pas.
		 */
		bool started;

		/**
		 * methode jouant un ficher de musique.
		 *
		 * @param filePath : le chemin du fichier a lancer.
		 */
		bool playMusic(const string& filePath);

		/**
		 * contructeur par defaut mis en private pour le pattern factory avec la classe SoundEngine
		 */
		MusicManager(void);

		/**
		 * destructeur par defaut mis en private pour que seul le SoundEngine (friend class) puisse le detruire.
		 */
		virtual ~MusicManager(void);
	public:
		/**
		 * methode ajoutant une musique au manager.
		 *
		 * @param filePath : le chemin du fichier. Ce chemin est verifié et il n'est ajouté que si un fichier existe
		 * réelement sur le disque.
		 * @return bool : true si le fichier a été ajouté, false sinon.
		 */
		bool addMusic(const string& filePath);

		/**
		 * methode permettant de charger un playListe.
		 *
		 * Une playList est un fichier commencant par "#define PLAYLIST" et contenant des chemin de fichier ou des
		 * commentaires commencant par #
		 *
		 * @param filePath : le chemin de la playlist.
		 * @param append : permet de savoir si la playList doit etre ajouté a la suite du manager ou si elle doit
		 * supprimer les fihier deja present puis j'ajouter.
		 *
		 * @return bool : true si la lecture s'est bien passé, false sinon.
		 */
		bool loadPlayList(const string& filePath, bool append = false);

		/**
		 * methode mettant a jour le manager. Passe a la musique suivant si il y a besoin.
		 */
		void update();

		/**
		 * stop la lecture de musique sur le manager.
		 */
		void stop();

		/**
		 * demarre la lecture de musique sur le manager.
		 */
		void start();

		/**
		 * met en pause le manager.
		 *
		 * @param pause : true => met en pause le manager, false => redemarre le manager.
		 */
		void pause(bool pause);

		/**
		 * methode permettant de savoir si le manager est en pause ou pas.
		 *
		 * @return bool : true si le manager est en pause, false sinon.
		 */
		bool isPaused();

		/**
		 * methode permettant de savoir si le manager est en train de jouer ou pas.
		 *
		 * @return bool : true => le manager est en train de jouer, false sinon.
		 */
		bool isPlaying();

		/**
		 * definit le volume du manager.
		 *
		 * @param volume : le volume du manager. Doit etre comprit entre 0 et 255
		 */
		void setVolume(int volume);

		/**
		 * methode retournant le volume du manager.
		 *
		 * @return int : le volume du manager.
		 */
		int	getVolume();

		/**
		 * retourne le temps (en ms) ecoulé de la musique en cours.
		 *
		 * @return int : le temps ecoulé en ms.
		 */
		int getElapsedTime();

		/**
		 * retourne la longeure totale de la musique (en ms)
		 *
		 * @return int : la longeurre totale de la musique en ms
		 */
		int getMusicLength();

		/**
		 * methode permettant de definire si le manager doit lire ses musiques de facon aleatoire ou pas.
		 *
		 * @param rand : true => lecture aleatoire, false sinon.
		 */
		void setRandom(bool rand);

		/**
		 * methode permattan de savoir si la lecture des musiques dans le manager se fait de facon aleatoire.
		 *
		 * @return bool : true => lecture aleatoire, false sinon.
		 */
		bool isRandom();

		/**
		 * methode permettant de definire si le manager doit recommencer la lecture de sa liste de chansons une fois
		 * qu'il a terminé.
		 *
		 * @param loop : true => manager boucle, false sinon.
		 */
		void setLooping(bool loop);

		/**
		 * methode permettant de savoir si le manager boucle dans la lecture de la playlist ou pas.
		 *
		 * @return bool : true => manager boucle, false sinon.
		 */
		bool isLooping();

		/**
		 * methode permettant de passer a la chanson suivante. La chanson courante est stoppée et la lecture de la
		 * chanson suivante commence (même si le manager n'avait pas été demarré.)
		 */
		void next();
	};
}// nameSpace SoundSystem


#endif
