function AppChat() {
	
}

AppChat.prototype = {
	'pChat' : null,
	'pLogin' : null,
	'updateTimer' : null,
	'UPDATE_TIME' : 3000,
	'connexion' : null,
	'instance' : null,
	'nomUtilisateur' : null,
	
	'getInstance' : function () {
		if (this.prototype.instance == null)
			this.prototype.instance = new AppChat();
		return this.prototype.instance;
	}
	,
	
	/**
	 * public void init()
	 * 
	 * Initialise l'application du chat
	 */
	
	'init' : function () {
		this.pLogin = new PanelLogin();
		// Pour le callback quand l'utilisateur est loggé //
		this.pLogin.setAppChatObj(this);
		// Affichage //
		this.pLogin.appendTo(document.body);
	}
	,
	
	/**
	 * private void refreshMessage()
	 * 
	 * Méthode qui est appelée à intervalle régulier et qui rafrachit les messages
	 * reçu et la liste des utilisateurs
	 */
	
	'refreshMessage' : function (){
		// Refresh des messages //
		this.connexion.executerCommande("getmsg", new Array(), function (resultat) {
			if (resultat.getCode() == 408) {
				// Une requête a pris trop de temps à être exécuté //
				return;
			}
			
			res = resultat.getJSON();
			
			if (isset(res.resultat) && res.resultat == "false") {
				this.logMessage(res.message);
				return;
			}
			
			for (var i=0; i<res.length; i++) {
				if (res[i].type == "privmsg" && !this.pChat.salleExist("~" + res[i].from)) {
					this.ajouterSalle("~" + res[i].from);
				}
				
				this.pChat.addContenu(
					((res[i].type == "msg") ? "#" + res[i].to : "~" + res[i].from),
					MessageFormat.format("msg", res[i])
				);
			}
		}.bind(this));
		
		// Update de la liste des utilisateurs dans toutes les salles //
		this.connexion.executerCommande("getutilisateurinsalle", new Array(), function (resultat) {
			if (resultat.getCode() == 408) {
				// Une requête a pris trop de temps à être exécuté //
				return;
			}
			
			var res = resultat.getJSON();
			
			if (isset(res.resultat) && res.resultat == "false") {
				this.logMessage(res.message);
				return;
			}
			
			for (var i in res) {
				if (typeof res[i] == "function")
					continue;
				this.pChat.updateUtilisateursListe("#" + i, res[i]);
			}
		}.bind(this));
		
		// Refresh des utilisateurs //
	}
	,
	
	/**
	 * public void ajouterSalle(String nom)
	 * 
	 * Ajouté visuellement une salle.
	 * À utiliser seulement si l'utilisateur est déjà connecté à cette salle
	 * 
	 * @param (String) nom
	 */
	
	'ajouterSalle' : function (nom) {
		this.pChat.addSalle(nom);
		this.pChat.setCurrentSalle(nom);
	}	
	,
	
	/**
	 * public void connexionSalle(String nom[, String password])
	 * 
	 * Se connecté à une salle et ajoute la salle si elle peut être rejoint sans erreur.
	 * 
	 * @param (String) nom
	 * @param (String) password Vide ou non-défini pour aucun mot de passe
	 */
	
	'connexionSalle' : function (nom, password) {
		var password = (isset(password)) ? password : '';
		nom = nom.split(" ").join("_");
		
		var cmd = CommandParse.prototype.parseCommande("/join " + nom + " " + password, this.pChat.getCurrentSalle());
		this.connexion.executerCommande(
			cmd.getCommandeName(),
			cmd.getCommandParam(), 
			cmd.getCallback().bind(this,cmd.getCommandParam()));
	}
	,
	
	/**
	 * public void quitterSalle(String nomSalle)
	 * 
	 * Fait la requête côté serveur de la fermeture de la salle par l'utilisateur
	 * et la ferme côté client une fois la requête confirmée.
	 * 
	 * @param (String) nomSalle
	 */
	
	'quitterSalle' : function (nomSalle) {
		this.connexion.executerCommande("quit", {"salle" : nomSalle}, function (salle ,resultat) {
			if (resultat.getCode() == 408) {
				// Une requête a pris trop de temps à être exécuté //
				return;
			}
			
			res = resultat.getJSON();
			
			if (res.resultat == "false") {
				this.logMessage(res.message);
				return;
			}
			
			this.pChat.removeSalle("#" + salle);
		}.bind(this, nomSalle));
	}
	,
	
	/**
	 * public void removeSalle(String nomSalle)
	 * 
	 * Efface visuellement la salle.
	 * 
	 * @param (String) nomSalle
	 */
	
	'removeSalle' : function (nomSalle) {
		this.pChat.removeSalle("#" + salle);
	}
	,
	
	/**
	 * public void connexionSucces(String nomUtilisateur)
	 * 
	 * Fonction appeler lorsque la connexion est faite avec succès.
	 * Le nom de l'utilisateur est du même coup garder en mémoire.
	 * 
	 * @param (String) nomUtilisateur
	 */
	
	'connexionSucces' : function (nomUtilisateur) {
		// On garde le nom choisi en mémoire //
		this.nomUtilisateur = nomUtilisateur;
		
		// On enlève le PanelLogin //
		this.pLogin.remove();
		
		// Affichage du PanelChat //
		this.pChat = new PanelChat();
		this.pChat.appendTo(document.body);
		
		// Correctif des menus pour IE //
		if (typeof fixIEMenu == "function")
			fixIEMenu();
			
		// Setup de la connexion AJAX //
		this.connexion = new PAFClient();
		this.connexion.setURL("ajax.php");
		this.connexion.setMethod("POST");
		this.connexion.setRetryOnFail(false);
		this.connexion.setTimeoutTime(1000);
		
		// Channel par défault //
		this.connexionSalle("Bienvenue");
		
		// Pour le rafraichissement des messages //
		this.updateTimer = setInterval(this.refreshMessage.bind(this), this.UPDATE_TIME);
		this.refreshMessage();
		
		// Setup des liens vers la classe App pour certain appel //
		this.pChat.setOnSendHandler(this.onMessageSend.bind(this));
		this.pChat.setAppObjRef(this);
	}
	,
	
	/**
	 * public void onMessageSend(String msg)
	 * 
	 * Méthode appelée lorsqu'un message est tapé.
	 * Faite l'analyse de ce qui est tapé et fait la requête.
	 * 
	 * @param (String) msg
	 */
	
	'onMessageSend' : function (msg) {
		var cmd = CommandParse.prototype.parseCommande(msg, this.pChat.getCurrentSalle());
		this.connexion.executerCommande(
			cmd.getCommandeName(),
			cmd.getCommandParam(), 
			cmd.getCallback().bind(this,cmd.getCommandParam()));
	}
	,
	
	/**
	 * public void ajouterMessage(String nomSalle, String message)
	 * 
	 * Ajout visuellement un message dans la salle spécifiée
	 * 
	 * @param (String) nomSalle
	 * @param (String) message
	 */
	
	'ajouterMessage' : function (nomSalle, message) {
		this.pChat.addContenu(nomSalle, message);
	}
	,
	
	/**
	 * public String getNomUtilisateur()
	 * 
	 * Retourne le nom de l'utilisateur en cours.
	 * 
	 * @return (String)
	 */
	
	'getNomUtilisateur' : function () {
		return this.nomUtilisateur;
	}
	,
	
	/**
	 * public Boolean salleExist()
	 * 
	 * Retourne si la salle spécifiée en paramètre existe
	 * 
	 * @return (Boolean)
	 */
	
	'salleExist' : function (nom) {
		return this.pChat.salleExist(nom);
	}
	,
	
	/**
	 * public void deconnexion()
	 * 
	 * Déconnecte l'utilisateur et redigire l'utilisateur une fois déconnectée.
	 */
	
	'deconnexion' : function () {
		this.connexion.executerCommande("logout", new Array(), function (resultat) {
			window.location.href = "index.html";
		});
	}
	,
	
	/**
	 * public void displayListeSalle()
	 * 
	 * Affiche la liste des salles crées et existantes sur le serveur
	 */
	
	'displayListeSalle' : function () {
		this.connexion.executerCommande("getlistesalles", new Array(), function (resultat) {
			var pListeSalle = new PanelListeSalle();
			pListeSalle.setAppChat(this);
			pListeSalle.fillListeSalle(resultat.getJSON());
			pListeSalle.appendTo(document.body);
		}.bind(this));
	}
	,
	
	/**
	 * public void initConvoPrivee(String nom)
	 * 
	 * Initialise une conversation privée avec le nom d'utilisateur spécifié
	 */
	
	'initConvoPrivee' : function (nom) {
		if (!this.salleExist("~" + nom) && nom != this.nomUtilisateur)
			this.ajouterSalle("~" + nom);
	}
	,
	
	/**
	 * public void logMessage(String msg)
	 * 
	 * Rajoute un message dans les logs affichés à l'utilisateur
	 */
	
	'logMessage' : function (msg) {
		this.pChat.logMessage(msg);
	}
}