#include "armafunc.h"


void move3D(std::string& clip, int statutConnec, std::vector<anyID>* liste_rc, std::vector<anyID>* liste_rl)
{
	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
		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.y;
			ss_z >> position.z;

			// 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 {	

	} //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);
		}
		
		// 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);
		}
		// 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);
		}
		
		// 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);
			}
			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 GetVersion(const char* version)
{
	std::string result = VERSION;
	// On balance tout dans le presse papier
	copyToClipboard (result);
}

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);
		}
	}
}

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);
		}
	}

	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);
		}
		// Récupération de l'ID du channel
		if(ts3Functions.getChannelOfClient(connecHandler, myID, &myChanID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getChannelOfClient", LogLevel_INFO, "Plugin", 0);
		}
		
		// 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)
	{

		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);
		}
		// Récupération de l'ID du channel
		if(ts3Functions.getChannelOfClient(connecHandler, myID, &myChanID) != ERROR_ok) {
			ts3Functions.logMessage("erreur getChannelOfClient", LogLevel_INFO, "Plugin", 0);
		}
		
		// 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();
	}
}