/*
 * TeamSpeak 3 plugin for ArmA 2
 * 
 * Authors: [BWF] Le CuLtO / [BWF] Johnson
 */

#include "plugin.h"

// Truc obligatoire
static struct TS3Functions ts3Functions;

// Handler de connexion
uint64 connecHandler;
// Statut de la connexion
int statutConnec;
// identity
char* identity;

// Variables de gestion des threads
bool fin_thread;
HANDLE hThreadPressePapier;
HANDLE hThreadSon;
CRITICAL_SECTION cs_tab;

// Fichiers son à jouer
static char* SON_RC	= "plugins\\arma2ts\\rc.wav";
static char* SON_RL	= "plugins\\arma2ts\\rl.wav";
static char* SON_BRUIT = "plugins\\arma2ts\\bruit.wav";

// Version
static char* VERSION = "arma2ts beta 0.8";

// Tableaux de mémorisation des différentes ID
std::vector<anyID> liste_rl, liste_rc;

// Variable gérant les "mute"
bool mute;

/* Unique name identifying this plugin */
const char* ts3plugin_name()
{
    return "ArmA 2 Plugin";
}

/* Plugin version */
const char* ts3plugin_version()
{
    return VERSION;
}

/* Plugin API version. Must be the same as the clients API major version, else the plugin fails to load. */
int ts3plugin_apiVersion()
{
	return 5;
}

/* Plugin author */
const char* ts3plugin_author()
{
    return "[BWF] Le CuLtO, [BWF] Johnson";
}

/* Plugin description */
const char* ts3plugin_description()
{
    return "TeamSpeak 3 plugin for ArmA 2.\nwww.blackwater.fr";
}

/* Set TeamSpeak 3 callback functions */
void ts3plugin_setFunctionPointers(const struct TS3Functions funcs)
{
    ts3Functions = funcs;
}

/*
 * Init du plugin, doit retourner 0 si tout va bien ou 1 en cas de problème
 */
int ts3plugin_init()
{
	// On récupère l'identity du joueur
	identity = new char[1000];
	getIdentity();
	
	// Récupération des handlers de connexion et du statut de connexion
	connecHandler = ts3Functions.getCurrentServerConnectionHandlerID();
	statutConnec = STATUS_DISCONNECTED;
	ts3Functions.getConnectionStatus(connecHandler, &statutConnec);
	
	// Initialisation sectin critique
	InitializeCriticalSection (&cs_tab);
	
	// initialisation variables de thread, etc...
	fin_thread = false;
	mute = false;
	
	// Creation des threads
	hThreadPressePapier = CreateThread (0, 0, BouclePressePapier, 0, 0, 0);
	hThreadSon = CreateThread (0, 0, BoucleSon, 0, 0, 0);

    return 0;  /* 0 = success, 1 = failure */
}

/* Custom code called right before the plugin is unloaded */
void ts3plugin_shutdown()
{
	// Arret de la boucle des threads
	fin_thread = true;

	// Attente arrêt thread presse papier
	if (hThreadPressePapier != 0) {
		WaitForSingleObject (hThreadPressePapier, INFINITE);
		CloseHandle (hThreadPressePapier);
	}
	// Attente arrêt thread son
	if (hThreadSon != 0) {
		WaitForSingleObject (hThreadSon, INFINITE);
		CloseHandle (hThreadSon);
	}
	
	// Suppression section critique
	DeleteCriticalSection (&cs_tab);

	// Liberation memoire du identity
	if (identity != NULL)
		delete identity;
}

/* Client changed current server connection handler */
void ts3plugin_currentServerConnectionChanged(uint64 serverConnectionHandlerID)
{
	connecHandler = serverConnectionHandlerID;
}

/* Changement de statut de la connexion */
void ts3plugin_onConnectStatusChangeEvent(uint64 serverConnectionHandlerID, int newStatus, unsigned int errorNumber)
{
	connecHandler = serverConnectionHandlerID;
	statutConnec = newStatus;
}

/*
 * Thread de surveillance des vectors pour jouer le son
 */
DWORD WINAPI BoucleSon (LPVOID lpParam)
{
	
	bool rc = false;
	bool rl = false;
	size_t taille_rc, taille_rl;
	
	while ( ! fin_thread )
	{
		if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
		{
			do
			{
				// Section critique sur les tableaux d'ID
				EnterCriticalSection(&cs_tab);
				taille_rc = liste_rc.size();
				taille_rl = liste_rl.size();
				LeaveCriticalSection (&cs_tab);
				
				if ( (taille_rc > 0) || (taille_rl > 0) )
				{
					// Si on passe de 0 à au moins une personne qui parle sur la RC
					if ( (! rc) && (taille_rc != 0) )
					{
						if (ts3Functions.playWaveFile(connecHandler, SON_RC) != ERROR_ok)
							ts3Functions.logMessage("erreur SON_RC", LogLevel_INFO, "Plugin", 0);
						rc = true;
						Sleep(1);
					}
					
					// Si on passe de 0 à au moins une personne qui parle sur la RL
					if ( (! rl) && (taille_rl != 0) )
					{
						if (ts3Functions.playWaveFile(connecHandler, SON_RL) != ERROR_ok)
							ts3Functions.logMessage("erreur SON_RL", LogLevel_INFO, "Plugin", 0);
						rl = true;
						Sleep(1);
					}
					
					// On joue le son du bruit si une des radios est activée
					if (ts3Functions.playWaveFile(connecHandler, SON_BRUIT) != ERROR_ok)
						ts3Functions.logMessage("erreur SON_BRUIT", LogLevel_INFO, "Plugin", 0);
					
					// Si personne parle sur la RC
					if ( (taille_rc == 0) && rc )
						rc = false;
					
					// Si personne parle sur la PL
					if ( (taille_rl == 0) && rl )
						rl = false;
					
					Sleep(818);
				}

			} while ( (taille_rc != 0) || (taille_rl != 0) );
		
			// Si plus personne parle sur les radio, réinitialisation des variables
			if (rc)
				rc = false;
			if (rl)
				rl = false;
			
			// Temps de pause de 0.05 de seconde
			Sleep(50);
		}
	}
	return 0;
}

/*
 * Thread de surveillance du presse papier
 */
DWORD WINAPI BouclePressePapier (LPVOID lpParam)
{

	// Variables de récup du presse papier
	std::string old_clip = "";
	std::string clip = "";
	unsigned int cpt_temps = 0;
	bool raz = false;
	
    while ( ! fin_thread )
	{
		
		// Récupération du contenu du presse papier
		if(OpenClipboard(0))
		{
			HANDLE h = GetClipboardData(CF_TEXT);
			if(h)
			{
				std::stringstream ss;
				char *s = (char *)GlobalLock(h);
				GlobalUnlock(h);
				CloseClipboard();
				ss << s;
				clip = ss.str();
			}
			CloseClipboard();
		} // fin recup presse papier
		
		// Si copier détecté
		if (clip.compare(old_clip) != 0)
		{
			//ts3Functions.logMessage(clip.c_str(), LogLevel_INFO, "Plugin", 0);

			// On mémorise la chaine en tant qu'ancienne pour une comparaison ultérieure
			old_clip = clip;

			// Si la chaine contient les balises de vérification
			if ( ( (clip.find("[bwf_arma2ts]")) == 0 ) && ( (clip.find("[/bwf_arma2ts]")) != -1 ) )
			{
				
				// Variable autorisant recentrage
				if ( ! raz )
					raz = true;
				cpt_temps = 0;

				// Variable de mémorisation des longueurs et positions de chaines
				size_t longueur, pos;
				// Variable de mémorisation du type de la trame
				std::string type_trame;

				// Supression de la balise "[bwf_arma2ts]"
				pos = clip.find("[bwf_arma2ts]") + 13;
				longueur = clip.size() - pos;
				clip = clip.substr(pos, longueur);

				// Supression de la balise "[/bwf_arma2ts]"
				pos = clip.find("[/bwf_arma2ts]");
				clip = clip.substr(0, pos);

				// Détection type de commande
				pos = clip.find("]");
				type_trame = clip.substr(1, pos - 1);
				clip = clip.substr(pos + 1, clip.size() - pos - 1);

				// Mode 3D, permet de positionner des ID dans l'espace
				if (type_trame == "3D")
				{
					move3D(clip);
				}

				// Mode GetPlayerID, renvoie l'ID du joueur
				else if (type_trame == "GetPlayerID")
				{
					getPlayerID(clip);
				}

				// Mode GetPlayerID, renvoie une ID correspondant à un pseudo donné en paramètre
				else if (type_trame == "GetPlayerIDFromName")
				{
					getPlayerIDFromName(clip);
				}
				
				// Permet d'activer ou non le mode mute si coordonnées [1000,1000,1000] en mode 3D
				else if (type_trame == "3DMUTE")
				{
					Mute3D(clip);
				}

				// Retourne la version du plugin
				else if (type_trame == "GetVersion")
				{
					std::string result = VERSION;
					// On balance tout dans le presse papier
					copyToClipboard (result);
				}

				// Switche un joueur dans le channel specifié
				else if (type_trame == "SwitchPlayer")
				{
					SwitchPlayer(clip);
				}

				// Connexion à un serveur
				else if (type_trame == "ConnectToServer")
				{
					ConnectToServer(clip);
				}

				// Renvoie l'ID du channel dans lequel se trouve le joueur
				else if (type_trame == "GetCurrentChannelID")
				{
					GetCurrentChannelID(clip);
				}

				// Renvoie l'ID du channel ayant le nom rentré en paramètre
				else if (type_trame == "GetChannelIDFromName")
				{
					//GetChannelIDFromName(clip);
				}

			} // fin chaine correcte

		} // fin copier détecté
		else
		{
			cpt_temps++;
		}

		// Recentrage des clients
		if ( (cpt_temps >= 20) && raz )
		{

			if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
			{
				cpt_temps = 0;
				raz = false;
				anyID myID;
				uint64 myChanID;
				anyID* clientsIDs;
				TS3_FMOD_VECTOR position;
				position.x = 0;
				position.y = 0;
				position.z = 0;

				// Ménages sur les tableaux d'ID
				liste_rc.clear();
				liste_rl.clear();

				// Récupération de l'ID du joueur
				if(ts3Functions.getClientID(connecHandler, &myID) != ERROR_ok) {
					ts3Functions.logMessage("erreur getClientID", LogLevel_INFO, "Plugin", 0);
				}
				// Récupération de l'ID du channel courant
				if(ts3Functions.getChannelOfClient(connecHandler, myID, &myChanID) != ERROR_ok) {
					ts3Functions.logMessage("erreur getChannelOfClient", LogLevel_INFO, "Plugin", 0);
				}
				// Récupération de la liste des clients sur le channel courant
				if(ts3Functions.getChannelClientList(connecHandler, myChanID, &clientsIDs) != ERROR_ok) {
					ts3Functions.logMessage("erreur getChannelClientList", LogLevel_INFO, "Plugin", 0);
				}
				// Recentrage de tous les clients
				for(int i=0; clientsIDs[i]; i++)
				{
					if (ts3Functions.fmod_Channelset3DAttributes(connecHandler,clientsIDs[i], &position, NULL) != ERROR_ok) {
						ts3Functions.logMessage("erreur Channelset3DAttributes", LogLevel_INFO, "Plugin", 0);
					}
				}
				
				// Libération mémoire du tableau
				ts3Functions.freeMemory(clientsIDs);

			} // fin statut connecte

		}
		else if (cpt_temps >= 20)
		{
			cpt_temps = 20;
		}

		// Temps de pause de la boucle
		Sleep(100);

	} // fin de boucle du thread
	return 0;
}

// Fonction de récupération de l'identity du joueur
void getIdentity()
{
	char* rep;
	std::string rep_fichier;

	// Récupération du répertoire du fichier de config
	rep = new char[1000];
	ts3Functions.getConfigPath(rep, 1000);
	rep_fichier = rep;
	rep_fichier += "ts3clientui_qt.secrets.conf";
	
	// Ouverture du fichier de config
	std::ifstream fichier( rep_fichier.c_str() );
    if ( fichier ) // ce test échoue si le fichier n'est pas ouvert
    {
		size_t pos1, pos2;
        std::stringstream buffer;

        buffer << fichier.rdbuf();
        fichier.close();

        rep_fichier = buffer.str();
		pos1 = rep_fichier.find("identity=");
		if (pos1 != -1) {
			pos2 = rep_fichier.find("\n", pos1);
			rep_fichier = rep_fichier.substr( pos1 + 9, pos2 - pos1 - 9);
			//ts3Functions.printMessageToCurrentTab(rep_fichier.c_str());
			strcpy(identity, rep_fichier.c_str());
		}
    }

	delete rep;
}

void move3D(std::string& clip)
{
	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{
		std::string trame;
		anyID pseudoID;
		TS3_FMOD_VECTOR position;
		size_t pos, longueur;
		
		// On vide les tableaux de listes de joueurs
		EnterCriticalSection(&cs_tab);
		liste_rc.clear();
		liste_rl.clear();

		// Analyse des trames de chaque unite
		while (clip.find("{") == 0)
		{
			
			std::stringstream ss_id, ss_x, ss_y, ss_z;

			// Extraction de la trame
			if ( clip.find("}{") != -1 )
				trame = clip.substr(1, clip.find("}{")-1);
			else
				trame = clip.substr(1, clip.size() - 2);
			
			// Extraction de l'ID
			pos = trame.find("[");
			ss_id << trame.substr(0, pos);
			ss_id >> pseudoID;
			trame = trame.substr( pos, trame.size() - pos );

			// Extraction position
			pos = trame.find(",");
			ss_x << trame.substr(1, pos - 1);
			trame = trame.substr(pos + 1, trame.size() - pos);
			pos = trame.find(",");
			ss_y << trame.substr(0, pos);
			trame = trame.substr(pos + 1, trame.size() - pos);
			pos = trame.find("]");
			ss_z << trame.substr(0, pos);
			trame = trame.substr(pos + 1, trame.size() - pos);

			// Sauvegarde position
			ss_x >> position.x;
			ss_y >> position.z;
			ss_z >> position.y;

			// Supression de la trame
			if (clip.find("}{") != -1) {
				pos = clip.find("}{") + 1;
				longueur = clip.size() - pos;
				clip = clip.substr(pos, longueur);
			} else {
				clip.assign("");
			}

			// Positionnement en 3D de l'ID extraite
			unsigned int id_correcte = ts3Functions.fmod_Channelset3DAttributes(connecHandler,pseudoID, &position, NULL);
			if (id_correcte == ERROR_ok)
			{
				
				/*// Si le mode mute est activé
				if (mute)
				{
					if ( (position.x == 1000) && (position.y == 1000) && (position.z == 1000) )
						ts3Functions.requestCl(connecHandler, pseudoID, -20);
					else
						ts3Functions.setClientVolumeModifier(connecHandler, pseudoID, 0);
				}*/

				/* Recherche mode audio
				 * CD => canal direct: les joueurs se parlent normalement
				 * RC => radio courte: si un joueur parle dans la radio courte un son spécifique est joué
				 * RL => radio longue: si un joueur parle dans la radio longue un son spécifique est joué
				 * Ici les ID en mode RC et RL sont juste ajoutées dans des tableaux
				 * Un thread à part analyse le contenu de ces tableaux et joue des sons en fonction de leur contenu
				 */
				if (strcmp(trame.c_str(), "[CD]") == 0)
				{
					// si le mec dans liste RC, on le supprime
					for (unsigned int i = 0; i < liste_rc.size(); i++)
						if (liste_rc[i] == pseudoID)
							liste_rc.erase(liste_rc.begin() + i);
					// si le mec dans liste RL, on le supprime
					for (unsigned int i = 0; i < liste_rl.size(); i++)
						if (liste_rl[i] == pseudoID)
							liste_rl.erase(liste_rl.begin() + i);
				}
				else if (strcmp(trame.c_str(), "[RC]") == 0)
				{
					bool ajoute = false;
					// on ajoute le mec s'il n'est pas deja dans la liste de RC
					for (unsigned int i = 0; i < liste_rc.size(); i++)
						if (liste_rc[i] == pseudoID)
							ajoute = true;
					if (! ajoute)
						liste_rc.push_back(pseudoID);
					// si le mec dans liste RL, on le supprime
					for (unsigned int i = 0; i < liste_rl.size(); i++)
						if (liste_rl[i] == pseudoID)
							liste_rl.erase(liste_rl.begin() + i);
				}
				else if (strcmp(trame.c_str(), "[RL]") == 0)
				{
					bool ajoute = false;
					// on ajoute le mec s'il n'est pas deja dans la liste de RL
					for (unsigned int i = 0; i < liste_rl.size(); i++)
						if (liste_rl[i] == pseudoID)
							ajoute = true;
					if (! ajoute)
						liste_rl.push_back(pseudoID);
					// si le mec dans liste RC, on le supprime
					for (unsigned int i = 0; i < liste_rc.size(); i++)
						if (liste_rc[i] == pseudoID)
							liste_rc.erase(liste_rc.begin() + i);
				}
			}
			else if (id_correcte == ERROR_client_invalid_id)
			{
				std::stringstream ss_error;
				std::string error;
				ss_error << "Erreur_ID_invalide:" << pseudoID;
				ss_error >> error;
				ts3Functions.logMessage(error.c_str(), LogLevel_INFO, "Plugin", 0);
			}
			else
			{
				std::stringstream ss_error;
				std::string error;
				ss_error << id_correcte;
				ss_error >> error;
				ts3Functions.logMessage(error.c_str(), LogLevel_INFO, "Plugin", 0);
			}

		} // fin while trouve des {	

		LeaveCriticalSection (&cs_tab);

	} //fin statut connecté

} // fin fonction move3D


void getPlayerID (std::string& clip)
{
	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{

		anyID myID = 0;
		std::string result;
		std::stringstream temp_stream;

		// Récupération de l'ID du joueur
		if(ts3Functions.getClientID(connecHandler, &myID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getClientID", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		
		// Envoi de l'ID dans la chaine de reponse
		temp_stream << myID;
		temp_stream >> result;

		// On balance tout dans le presse papier
		copyToClipboard (result);

	} // fin statut connecté

} // fin fonction getPlayerID

void getPlayerIDFromName (std::string& clip)
{
	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{
		anyID myID, pseudoID;
		uint64 myChanID;
		anyID* clientsIDs;
		char* sPseudo;
		bool trouve;
		std::string result;
		std::stringstream temp_stream;
		
		// Récupération de l'ID du joueur
		if(ts3Functions.getClientID(connecHandler, &myID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getClientID", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		// Récupération de l'ID du channel courant
		if(ts3Functions.getChannelOfClient(connecHandler, myID, &myChanID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getChannelOfClient", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		// Récupération de la liste des clients sur le channel courant
		if(ts3Functions.getChannelClientList(connecHandler, myChanID, &clientsIDs) != ERROR_ok) {
			ts3Functions.logMessage("erreur getChannelClientList", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		
		// Vérification de la correspondance des pseudo
		trouve = false;
		for(int i=0; clientsIDs[i]; i++)
		{
			// Récupération du pseudo du client
			if(ts3Functions.getClientVariableAsString(connecHandler,clientsIDs[i],CLIENT_NICKNAME,&sPseudo) != ERROR_ok)
			{
				ts3Functions.freeMemory(clientsIDs);
				result = "-1";
				copyToClipboard (result);
				return;
			}
			if (strcmp(clip.c_str(), sPseudo) == 0)
			{
				trouve = true;
				pseudoID = clientsIDs[i];
			}
		}
		ts3Functions.freeMemory(clientsIDs);
		ts3Functions.freeMemory(sPseudo);
		
		// Envoi de l'ID dans la chaine de reponse
		if (trouve)
			temp_stream << pseudoID;
		else
			temp_stream << -1;
		temp_stream >> result;
		
		// On balance tout dans le presse papier
		copyToClipboard (result);

	} // fin statut connecté
}

void Mute3D(std::string& clip)
{
	if (clip == "ON")
		mute = true;
	else
		mute = false;
}

void SwitchPlayer(std::string& clip)
{
	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{
		size_t pos;
		std::string idPlayer, idChannel, mdp;
		std::stringstream temp_idp, temp_idc;
		anyID idP;
		uint64 idC;

		// Extraction ID joueur
		pos = clip.find(",");
		idPlayer = clip.substr(0, pos);
		clip = clip.substr( pos + 1, clip.size() - pos );
		temp_idp << idPlayer.c_str();
		temp_idp >> idP;
		//ts3Functions.printMessageToCurrentTab(idPlayer.c_str());
		
		// Extraction ID channel
		pos = clip.find(",");
		idChannel = clip.substr(0, pos);
		clip = clip.substr( pos + 1, clip.size() - pos );
		temp_idc << idChannel.c_str();
		temp_idc >> idC;
		//ts3Functions.printMessageToCurrentTab(idChannel.c_str());

		//  Extraction mot de passe
		mdp = clip;
		//ts3Functions.printMessageToCurrentTab(mdp.c_str());
		
		// Appel fonction de switch
		if(ts3Functions.requestClientMove(connecHandler, idP, idC, mdp.c_str(), NULL) != ERROR_ok) {
			ts3Functions.logMessage("erreur requestChannelMove", LogLevel_INFO, "Plugin", 0);
			return;
		}
	}
}

void ConnectToServer(std::string& clip)
{
	size_t pos;
	std::string ip, port, pseudo, mdp, channel;
	char** tabChannels = NULL;
	int cpt_chan = 1;
	std::stringstream temp_port;
	int port_u;

	//ts3Functions.printMessageToCurrentTab(clip.c_str());

	// Extraction IP
	pos = clip.find(",");
	ip = clip.substr(0, pos);
	clip = clip.substr( pos + 1, clip.size() - pos );
	//ts3Functions.printMessageToCurrentTab(ip.c_str());

	// Extraction port
	pos = clip.find(",");
	port = clip.substr(0, pos);
	clip = clip.substr( pos + 1, clip.size() - pos );
	temp_port << port.c_str();
	temp_port >> port_u;
	//ts3Functions.printMessageToCurrentTab(port.c_str());

	//  Extraction mot de passe
	pos = clip.find(",");
	mdp = clip.substr(0, pos);
	clip = clip.substr( pos + 1, clip.size() - pos );
	//ts3Functions.printMessageToCurrentTab(mdp.c_str());

	// Extraction Channel par defaut
	/*pos = clip.find(",");
	channel = clip.substr(1, pos - 1);
	clip = clip.substr( pos + 1, clip.size() - pos );
	ts3Functions.printMessageToCurrentTab(channel.c_str());
	// Si un channel est specifié
	if(channel.size() != 0)
	{
		// On compte le nombre de channels
		for (int i =0; i < channel.size(); i++)
			if (channel.c_str()[i] == ';')
				cpt_chan++;
		// Allocation mémoire du tableau de strings
		tabChannels = new char*[cpt_chan+1];
		int pos_tab = 0;
		// Parcours du tableau et allocation de chaque string
		do {
			pos = channel.find(";");
			if (pos != -1)
			{
				tabChannels[pos_tab] = new char[pos+1];
				for (int i = 0; i < pos+1; i++)
				{
					tabChannels[pos_tab][i] = channel.c_str()[i];
					if (i == pos)
						tabChannels[pos_tab][i] = '\0';
				}
				channel = channel.substr(pos + 1, channel.size() - pos);
				ts3Functions.printMessageToCurrentTab(channel.c_str());
			}
			else
			{
				tabChannels[pos_tab] = new char[channel.size()+1];
				for (int i = 0; i < channel.size()+1; i++)
				{
					tabChannels[pos_tab][i] = channel.c_str()[i];
					if (i == channel.size())
						tabChannels[pos_tab][i] = '\0';
				}
			}
			pos_tab++;
		} while (pos != -1)
	}*/

	// Extraction pseudo
	pseudo = clip;
	//ts3Functions.printMessageToCurrentTab(pseudo.c_str());
	if (pseudo.size() == 0)
		pseudo = "TS3 User";

	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{
		// Déconnexion du serveur actuel
		if(ts3Functions.stopConnection(connecHandler, "ConnectToServer") != ERROR_ok) {
			ts3Functions.logMessage("erreur stopConnection", LogLevel_INFO, "Plugin", 0);
			return;
		}
	}

	while (statutConnec != STATUS_DISCONNECTED) {}

	ts3Functions.startConnection(connecHandler, identity, ip.c_str(), port_u, pseudo.c_str(), NULL, "", mdp.c_str());

}

void GetCurrentChannelID (std::string& clip)
{
	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{

		anyID myID = 0;
		uint64 myChanID;
		std::string result;
		std::stringstream temp_stream;

		// Récupération de l'ID du joueur
		if(ts3Functions.getClientID(connecHandler, &myID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getClientID", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		// Récupération de l'ID du channel
		if(ts3Functions.getChannelOfClient(connecHandler, myID, &myChanID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getChannelOfClient", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		
		// Envoi de l'ID dans la chaine de reponse
		temp_stream << myChanID;
		temp_stream >> result;

		// On balance tout dans le presse papier
		copyToClipboard (result);

	} // fin statut connecté
}

/*void GetChannelIDFromName (std::string& clip)
{
	if(statutConnec == STATUS_CONNECTION_ESTABLISHED)
	{

		uint64 myChanID;
		char* list_chan;
		std::string result;
		std::stringstream temp_stream;

		// Récupération de la liste de channels

		
		// Récupération de l'ID du channel
		if(ts3Functions.getChannelOfClient(connecHandler, myID, &myChanID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getChannelOfClient", LogLevel_INFO, "Plugin", 0);
			result = "-1";
			copyToClipboard (result);
			return;
		}
		
		// Envoi de l'ID dans la chaine de reponse
		temp_stream << myChanID;
		temp_stream >> result;

		// On balance tout dans le presse papier
		copyToClipboard (result);

	} // fin staut connecté

}*/

// Fonction de copie de données texte dans le presse papier
void copyToClipboard (std::string& txt)
{
	if ( OpenClipboard(NULL) )
	{
		HGLOBAL clipbuffer;
		char * buffer;
		EmptyClipboard();
		clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(txt.c_str()) + 1);
		buffer = (char*)GlobalLock(clipbuffer);
		strcpy(buffer, txt.c_str());
		GlobalUnlock(clipbuffer);
		SetClipboardData(CF_TEXT, clipbuffer);
		CloseClipboard();
	}
}