#ifndef ConfigIniParser_class
#define ConfigIniParser_class


#include <map>
#include <vector>
#include <sstream>

using namespace std;

    enum separateurs{EGAL='=',COMENT=';'};
    const string ENTETE="  __COMMENTAIRES_DENTETE";
    const string ERREUR="ERROR";
    const bool DEBUG=false;

    struct entry
    {
        string variable;
        string valeur;
        string commentaire;
    };


    class ConfigIniParser {

	public:
		ConfigIniParser();
		ConfigIniParser(string fichier);
		~ConfigIniParser();

		string m_fichier;

		bool getSection(string section);



		/**
		*      \fn     bool open(string fichier="config.ini");
		*      Fonction ouverture d'un fichier.ini
		*      \brief  ConfigIniParser.open("fichier.ini") /default=config.ini
		*      \param  string fichier
		*/
		bool open();
		/**
		*      \fn     bool save(string fichier="config.ini");
		*      \brief  ConfigIniParser.save("fichier.ini") /default=config.ini
		*/
		bool save();
		entry getEntry(const string& section,const string& variable);
		/**
		*      \fn string getValeur(const string& section, const string& variable);
		*      \brief Retourne la valeur correspondant a la variable demandée
		*/
		string getValeur(const string& section, const string& variable); //old way
		template<class T>
		bool getValeur(const string& section, const string& variable, T& destination);
		string getComment(const string& section, const string& variable);
		bool addEntry(const string& section, const entry& e); //a eviter
		bool addComment(const string& section, const string& commentaire); //en debut de section
		bool setComment(const string& section, const string& variable, const string& commentaire); //sur une ligne
		template<class T>
		bool setValeur(const string& section, const string& variable , const T& valeur);
		template<class T>
		bool addValeur (const string& section, const string& variable , const T& valeur); //forme generique
		//bool addValeur(const string& section, const string& variable , const int& valeur);
		//bool addValeur(const string& section, const string& variable , const double& valeur);
		bool addSection(const string& section, const unsigned int& position);
		bool eraseEntry(const string& section, const string& variable);
		bool eraseSection(const string& section);
		/**todo
		bool eraseValeur();
		*/
		unsigned int begin();
		unsigned int end();
	
		
	
	protected:
		bool m_erreur;

		map<string,vector<entry> > m_config;    //le fichier config sera contenu ici
		vector<string> m_structure;             //preserve la 'structure' (l'ordre) du fichier
		string m_getSection(const string ligne);
		void m_makeEntry(entry* e,const string ligne);
		void m_sStrip(string* s, const char c);
    };


    template<typename T>
    string toStr(const T& v){
        ostringstream oss;
        oss<<v;
        return oss.str();
    }


    template<typename T>
    bool fromStr(const string& v, T& dest ){
        istringstream iss(v);
        return iss >> dest != 0;
    }


    template<typename T>
    bool ConfigIniParser::addValeur(const string& section, const string& variable , const T& valeur){
        if(m_config.find(section)==m_config.end())return false;
        entry e;
        e.commentaire="";
        e.valeur=toStr(valeur);
        e.variable=variable;


// 	cout << "valeur=" << valeur << " et variable=" << variable << endl;

        m_config[section].insert(m_config[section].begin(),e);
        return true;
    }


    template<typename T>
    bool ConfigIniParser::setValeur(const string& section, const string& variable , const T& valeur){
        if(m_config.find(section)==m_config.end())return false;
        vector<entry> v=m_config[section];
        for(unsigned int i =0; i<v.size() ;i++){
            if(v[i].variable==variable){
                v[i].valeur=toStr(valeur);
                m_config[section]=v;
                return true;
            }
        }
        return false;
    }


    template<typename T>
    bool ConfigIniParser::getValeur(const string& section, const string& variable,T& destination){
        m_erreur=false;
        if (variable!="" && section!=""){
            for(unsigned int i=0; m_config[section].size();i++){
                if(m_config[section][i].variable==variable){
                    return fromStr(m_config[section][i].valeur,destination);
                }
            }
        }
        m_erreur=true;
        return false;
    }





#endif

