#ifndef PLAYLIST_H
#define PLAYLIST_H

#include <string>
#include <vector>
#include <fstream>

using namespace std;

namespace SoundSystem
{
	/**
	* classe gerant une playList de chansons.
	*
	* Cette classe permet de gerer facilement une playlist de musiques. Elle permet de charger un playlist depuis un
	* fichier et d'ajouter des chansons par la suite.
	*
	* Une propriété interessante de la playlist est qu'une musique n'est ajouté que si elle existe effectivement sur
	* le disque, ainsi, l'utilisateur peut utiiser la playlist sans craindre de tomber sue un fichier n'existant pas.
	*
	* Elle peut aussi gerer les fichier de facon aleatoire. On peut d'ailleur noter que cette gestion n'est pas
	* totalement aleatoire car la playlist ne remettra par une musique tant que toutes les musiques ne sont pas passée,
	* ainsi elle assure que chaque musique sera jouée au moins une fois par cycles (excepté si on enleve le mode aleatoire).
	*/
	class PlayList
	{
	private:
		/**
		* permet de savoir si la playlist est gerée de facon aleatoire ou pas.
		*/
		bool random;

		/**
		* permet de savoir si la playlist boucle ou pas.
		*/
		bool loop;

		/**
		* la liste de nom de fichiers de la playlist. chaque fichier present dans cette list est testé, c'est a dire que
		* le fichier existe bien sur le disque.
		*/
		vector<string> list;

		/**
		* le vecteur l'index utilisé lors de la lecture aleatoire. chaque case du vecteur represent un index dans la 
		* liste de fichier, et chaque index est present une et une seule fois. ceci permet de s'assurer que chaque 
		* chanson sera joué et qu'elle ne sera jouée qu'une fois par boucle de playlist.
		*/ 
		vector<int> randomIndex;

		/**
		* l'index courant de lecture. en mode random cet index indique l'index dans le vecteur d'index aleatoire, alors
		* qu'en mode non random, il indique l'index dans la liste des fichiers.
		*/
		int index;

		/**
		* methode permettant d'initialiser le vecteur d'index aleatoire entre 2 bornes de la list de fichier.
		*
		* cette methode permet de n'initialiser qu'une partie du vecteur si, par exemple, l'utilisateur passe de non random
		* a random en cours de lecture, cette methode permet de n'initialiser que les index qui ne sont pas encore passé, 
		* ainsi, seul la fin de la playlist est melangée.
		*
		* @param begin : l'index de debut a partire du quel commence la generation des index aleatoires.
		* @param end : l'index de fin de generation des nombres aleatoire.
		*/
		void initRandom(int begin, int end);

		/**
		* methode effectuant un tirage aleatoire d'un index entre 2 bornes, et echange l'index passé en parametre avec
		* l'index tiré.
		*
		* @param indexMin : la borne inferieurs lors du tirage aleatoire
		* @param indexMax : la borne superieure lors du tirage aleatoire.
		* @param waorkIndex : l'index qui sera echangé avec l'index tiré au hazard.
		*/
		void tirage(int indexMin,int indexMax, int workIndex);
	public:
		/**
		* constructeur par defaut.
		*/ 
		PlayList(void);

		/**
		* destructeur par defaut.
		*/ 
		virtual ~PlayList(void);

		/**
		* methode retournant le nom du fichier de la prochaine musique dans la playlist en fonction du mode de gestion
		* utilisé (random/loop)
		*/
		string next();

		/**
		* methode definissant si la playlist doit utiliser une gestion aleatoire de la musique ou pas.
		*
		* @param rand : true => gestion aleatoire, false sinon.
		*/
		void setRandom(bool rand);

		/**
		* methode permettant de savoir si la playlist utilise une gestion aleatoire.
		*
		* @return bool : true => la playlist utilise une gestion aleatoire des musique, false sinon.
		*/
		bool isRandom();

		/**
		* methode permettant de definire si la playlist doit boucler ou pas.
		*
		* @param loop : true => la playlist doit bouler, flase sinon.
		*/
		void setLooping(bool loop);

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

		/**
		* methode permettant de savoir si la playlist est arrivée a la fin de sa liste de fichier ou pas.
		*
		* @return bool : true => la playlist est terminé, il ne reste plus de fichier a jouer. false sinon.
		*/
		bool isFinish();

		/**
		* methode retournant le nombre de fichier valides dans la playliste.
		*
		* @return int : le nombre de fichier valides presents dans la playlist.
		*/
		int size();

		/**
		* methode permettant de charger un fichier de playlist.
		*
		* un fichier de playlist commence obligatoirement dans sa premiere ligne par : 
		*
		* #define PLAYLIST
		*
		* Ensuite, il contient soit des chemin de fichier, soit des commentaires dont le premier
		* caractere est #.
		*
		* Le fichier de playlist peut soit remplacer la playlist precedente, soit etre ajouté a la suite de la playlist
		* precedente.
		*
		* @param filePath : le nom du fichier de playlist.
		* @param append : permet de savoir si le fichier de playlist doit etre ajouté a la fin de la playlist courante
		* ou la remplacer.
		*
		* @return bool : true => le chargement s'est bien passé, false sinon.
		*/
		bool load(const string& filePath, bool append = false);

		/**
		* methode nettoyant la playlist.
		*/
		void clear();

		/**
		* methode ajoutant un fichier a la playlist.
		*
		* Seul les fichier existants réelement sur le disque sont ajouté a la playlist.
		*
		* @param filePath : le chemin du fichier sur le disque.
		*
		* @return bool : true => l'ajout du fichier s'est bien passé, false => l'ajout n'a pas pu etre efectué, probalement
		* car le fichier n'existe pas sur le disque.
		*/
		bool add(const string& filePath);

		/**
		* methode demarrant la playlist depuis le debut.
		*/
		void start();
	};
};// namespace SoundSystem;

#endif
