/************************************************************************************
@ Author : Nicolas Castelli
@ Mail : nicolas.castelli2@gmail.com
@ Date of creation : 2008-01-01
@ Filename : MyDeck.js
@ Use : Définition de la classe permettant de créer l'interface de gestion
des decks
************************************************************************************/

/************************************************************************/
/***********************  |VSDECKMAKER : DECK|  *************************/
/************************************************************************/
//Classe pour le deck du DeckMaker
MyDeck_VSDeckMaker = function() {
	//**** VARIABLES PRIVÉES
	var id = "";
	var htmlCard = "";
	//Menu de transfert à afficher
	var transferMenuMode = 1;
	var transferMenu = "";
	var transferElt = new Array();
	//Pool de cartes
	var pool = new Array();
	//Composants HTML spécifiques
	//Boutons
	var compBt_OrderName = "";
	var compBt_OrderCost = "";
	var compBt_OrderType = "";
	//Pour le tri de cartes
	var sortActions = new Array(0, 0, 0);

	//**** VARIABLES PUBLIQUES


	//**** FONCTIONS PRIVÉES
	//Colorie les lignes depuis la
	//première (hors caché en entête) en alternant les styles 1 ligne sur 2
	var harmonizeDeck = function() {
		var newClass = new Array("class1", "");
		var newClassIndex = 0;
		//Mise à jour
		for(var i=1; i < $(id).rows.length; i++)
		{
			var row = $(id).rows[i];
			//On met à jour toutes les cellules de la ligne
			updateRowCSS(row.id, newClass[newClassIndex]);
			(newClassIndex == 1) ? newClassIndex = 0 : newClassIndex = 1;
		}
	}

	//Change la classe de toutes les cellules d'une ligne
	var updateRowCSS = function(rowId, className) {
		for(var j=0; j < $(rowId).cells.length; j++)
		{
			$(rowId).cells[j].className = className;
		}
	}

	//*********************** AJOUT DE LIGNES **************************/
	//Ajoute une ligne dans le tableau du deck
	var addRow = function(card, qty) {
		var rowId = "";
		var newRow = "";
		var newCell = "";
		//On ajoute une ligne au tableau
		newRow = $(id).insertRow(-1);//-1 : La ligne sera ajoutée à la fin du tableau
		//On crée un identifiant unique pour la ligne ajoutée
		rowId = id + "_" + card.nom + "#" + card.shortset;
		newRow.id = rowId;
		//Qté
		newCell = newRow.insertCell(0);
		newCell.innerHTML = qty;
		newCell.style.width = "5%";
		initCell(newCell, rowId);
		//Nom
		newCell = newRow.insertCell(1);
		//Gestion des versions localisées
		if(card.nom_lang)
			newCell.innerHTML = card.nom_lang.replace(/&apos;/gi, "'");
		else
			newCell.innerHTML = card.nom.replace(/&apos;/gi, "'");
		newCell.style.width = "45%";
		initCell(newCell, rowId);
		//Coût
		newCell = newRow.insertCell(2);
		newCell.innerHTML = card.couthtml;
		newCell.style.width = "22%";
		initCell(newCell, rowId);
		//Type
		newCell = newRow.insertCell(3);
		if(card.nom_lang)
			newCell.innerHTML = card.type_lang;
		else
			newCell.innerHTML = card.type;
		newCell.style.width = "22%";
		initCell(newCell, rowId);
		//Set
		newCell = newRow.insertCell(4);
		newCell.innerHTML = card.shortset;
		newCell.style.width = "8%";
		initCell(newCell, rowId);
	}

	//Ajoute les fonctions qui vont bien sur les cellules "nom" et "quantité" du deck
	var initCell = function(element, rowId) {
		//On Mouse Over : on affiche la carte survolée
		element.onmouseover = function(){ mouseOverCard(rowId); };
		//On Click : on affiche le menu de transfert des cartes
		if (globalBrowser.getNavigator() == "Internet Explorer" )
			element.onclick = function() { mouseClickCard(event, rowId); } ;
		else
			element.onclick = function(event) { mouseClickCard(event, rowId); } ;
	}

	//*********************** MAJ LIGNES ************************/
	//Mise à jour de la quantité d'une ligne
	var updateRow = function(card, qty) {
		var cardRowId = id + "_" + card.nom + "#" + card.shortset;
		var cardIndex = getCardIndexByKey(card.nom + "#" + card.shortset);
		updateRowQty(cardRowId, qty, cardIndex);
	}

	//Mise à jour de la quantité d'une carte sur une ligne
	var updateRowQty = function(rowId, qty, cardIndex) {
		var cell = $(rowId).cells[0];
		var newQty = parseInt(cell.innerHTML) + qty;
		//Si la nouvelle quantité est > 0, on l'affiche, sinon, on supprime
		//la carte du tableau et du pool
		if(newQty > 0)
			cell.innerHTML = newQty;
		else
		{
			$(id).deleteRow(getRowIndex(rowId));
			deleteFromArray(pool, cardIndex);
		}
	}

	//Retourne le numéro de ligne de la carte dans le tableau
	var getRowIndex = function(rowId) {
		var pos = 0;
		var rows = $(id).rows;
		for(var i=0; i < rows.length; i++)
		{
			var row = rows[i];
			if(row.id == rowId)
			{
				pos = i;
				break;
			}
		}
		return pos;
	}

	//Retourne l'indice de la carte dans le pool en fonction de la clé unique
	//Nom_carte + InitSet_Carte
	//Modif 25/07/2009 : attention au traitement des noms contenant des apostrophes : j'encode la cardKey pour parser les apostrophes
	var getCardIndexByKey = function(cardKey) {
		var cardIndex = -1;
		//
		var adaptedKey = cardKey.replace(/\'/gi, "&apos;")
		for(var i=0; i < pool.length; i++)
		{
			var cardTmp = pool[i];
			var cardKeyTmp = cardTmp.nom + "#" + cardTmp.shortset;
			if( cardKeyTmp == adaptedKey)
			{
				cardIndex = i;
				break;
			}
		}
		return cardIndex;
	}

	/**********  GESTION DES EVENEMENTS SUR LES CARTES DU DECK  **********/
	//Quand on survole avec la souris une des cartes du classeur  :
	//1) On affiche le grand scan
	//2) On met à jour le texte sous la carte
	var mouseOverCard = function(idElt) {
		var tTmp = idElt.split("_");
		var keyTmp = tTmp[1];
		var cardIndex = getCardIndexByKey(keyTmp);
		var card = pool[cardIndex];
		if (card)
		{
			if(localVersion == 1)
			{
			//VERSION LOCALE
			htmlCard.updateText(card);
			}
			else
			{
				//VERSION NORMALE
				htmlCard.updateScan(card);
				htmlCard.updateText(card);
			}
		}
	}

	//Gestion du clic gauche sur une carte du deck
	var mouseClickCard = function(evt, idElt) {
		var tTmp = idElt.split("_");
		var keyTmp = tTmp[1];
		var cardIndex = getCardIndexByKey(keyTmp);
		var cardToTrf = pool[cardIndex];
		var cardQty = parseInt($(idElt).cells[0].innerHTML);
		var cardClass = $(idElt).cells[0].className;

		//Si le bouton ALT est pressé en même temps que le clic gauche
		//alors sélection multiple de cartes
		if(evt.altKey)
		{
			//Si la carte a déjà été selectionnée, il faut la deselectionner
			//et la supprimer de la liste de transfert
			if(cardClass == "class3")
			{
				deleteCardForTransfert(cardToTrf);
				transferMenu.close();
				harmonizeDeck();
			}
			else
			{
				transferElt.push(new Array(cardToTrf, cardQty));
				//On colorie sa ligne
				updateRowCSS(idElt, "class3");
				//On prépare le transfert pour la carte sélectionnée
				transferMenu.prepareTransfert(evt, transferElt, transferMenuMode, id);
			}
		}
		else //Sélection simple
		{
			//Réinitialisation
			harmonizeDeck();
			transferElt.length = 0;
			//Si la carte a déjà été selectionnée, il faut la deselectionner
			//et la supprimer de la liste de transfert
			if(cardClass == "class3")
			{
				deleteCardForTransfert(cardToTrf);
				transferMenu.close();
				harmonizeDeck();
			}
			else
			{
				transferElt.push(new Array(cardToTrf, cardQty));
				//On colorie sa ligne
				updateRowCSS(idElt, "class3");
				//On prépare le transfert pour la carte sélectionnée
				transferMenu.prepareTransfert(evt, transferElt, transferMenuMode, id);
			}
		}
	}

	//Supprime une carte du tableau de transfert
	var deleteCardForTransfert = function(cardToTrf) {
		for(var i=0;i < transferElt.length; i++)
		{
			var cardTmp = transferElt[i][0].nom + "_" + transferElt[i][0].shortset;
			if( cardTmp == cardToTrf.nom + "_" + cardToTrf.shortset)
			{
				deleteFromArray(transferElt, i);
				break;
			}
		}
	}

	//***************** TRI DES CARTES *****************//
	//Pour ordonner les cartes du spoiler texte
	var sortDeck = function(sortMethod) {
		//1) ON MODIFIE L'ORDRE DE RANGEMENT DU POOL DE BASE
    determinePoolOrder(sortMethod);
		//2)ON VIDE LE DECK PUIS ON LE REMPLIT AVEC LES LIGNES CLASSEES
		orderDeck();
	}

	//Pour classer le deck
	var orderDeck = function() {
		var arrRows = $(id).rows;
		var qty = 0;
		var name = "";
		var initSet = "";
		var cardIndex = 0;
		var arrTmp = new Array();
		//On récupère le tableau actuel
		for(var i=0; i < arrRows.length; i++)
		{
			qty = parseInt(arrRows[i].cells[0].innerHTML);
			name = arrRows[i].cells[1].innerHTML;
			initSet = arrRows[i].cells[4].innerHTML;
			cardIndex = getCardIndexByKey(name + "#" + initSet);
			arrTmp[cardIndex] = qty;
		}
		//On vide le tableau
		emptyDeck();
		//On remplit le tableau avec les lignes classées
		for(var i=0; i < pool.length; i++)
		{
			var card = pool[i];
			cardIndex = getCardIndexByKey(card.nom + "#" + card.shortset);
			qty = arrTmp[cardIndex];
			addRow(card, qty);
		}
		//3) ON HARMONISE A JOUT LES LIGNES DU DECK
		harmonizeDeck();
	}

	//Pour vider le deck (suppression des lignes)
	var emptyDeck = function() {
		var arrRows = $(id).rows;
		var start = arrRows.length-1;
		for(var i=start; i >= 1; i--)
		{
			$(id).deleteRow(i);
		}
	}

	//Le pool de cartes est trié par ordre alphabétique
	var determinePoolOrder = function(method) {
		var sToSort = "";
		var sFinalToSort = "";
		var arrTmp = new Array();
		var aPreSort = new Array();
		var vDim = "";
		var vDimVal = ""
		for(var i = 0; i < pool.length; i++)
		{
			var card = pool[i];
			vDim = "";
			vDimVal = card.nom + "#" + i;
			if(method == "NAME")
			{
				if(card.nom_lang)
				{
					vDim = card.nom_lang;
					vDimVal = card.nom_lang + "#" + i;
				}
				else
					vDim = card.nom;
			}
			else if(method == "TYPE")
				vDim = card.type + "_" + card.soustype;
			else if(method == "COST")
				vDim = card.valeurcout + "_" + card.cout;

			//Un tableau où, pour chaque valeur de la dimension donnée,
			//on a la liste des noms de cartes associés
			if(!aPreSort[vDim])
				aPreSort[vDim] = new Array();
			aPreSort[vDim].push(vDimVal);
			//Les cartes doivent rester triées par ordre alpha
			aPreSort[vDim].sort();
		}
		sortPool(aPreSort, method);
	}

	//Classe le tableau
	var sortPool = function(aCards, method, aOrder) {
		var vKey = "";
		var vIndex = 0;
		var orderPool = new Array();
		//Si un ordre de classement est défini, on l'utilise
		//Sinon, il s'agit simplement de l'ordre croissant
		if(!aOrder)
		{
			var aOrder = new Array();
			for(k in aCards)
			{
				aOrder.push(k);
			}
			aOrder.sort();
		}
		//On classe le pool
		for(var i = 0; i < aOrder.length; i++)
		{
			vKey = aOrder[i];
			for(var j = 0; j < aCards[vKey].length; j++)
			{
				//La valeur récupérée est : card.nom + "#" + i
				vIndex = parseInt(aCards[vKey][j].split("#")[1]);
				orderPool.push(pool[vIndex]);
			}
		}
		//Affectation finale
		pool.length = 0;
		pool = orderPool.slice();
		orderPool.length = 0;
		if( (method == "NAME" && sortActions[0] == 0) ||
				(method == "TYPE" && sortActions[1] == 0) ||
				(method == "COST" && sortActions[2] == 0)
		  )
		{
			invertArray(pool);
		}

	}

	//On enregistre le type de classement effectué
	var updSortActions = function(vIndex) {
		var vVal = sortActions[vIndex];
		if(vVal == 0)
			sortActions[vIndex] = 1;
		else
			sortActions[vIndex] = 0;
	}

	//********************* STATISTIQUES ********************//

	//Remise à zéro des stats dans l'entete du deck
	var resetDeckHeader = function() {
		//On affecte la valeur aux composants HTML
		$(id + "HeaderTotal").innerHTML = 0;
		$(id + "HeaderCreature").innerHTML = 0;
		$(id + "HeaderLand").innerHTML = 0;
	}

	//Calcule les stats  dans l'entete du deck à chaque modification. Affiche le nombre
	//de terrains et de creatures.
	var setDeckHeader = function(card, qty) {
		var total = parseInt($(id + "HeaderTotal").innerHTML);
		var creature = parseInt($(id + "HeaderCreature").innerHTML);
		var land = parseInt($(id + "HeaderLand").innerHTML);
		if(card.type.toLowerCase().hasWord("creature"))
			creature += qty;
		if(card.type.toLowerCase().hasWord("land"))
			land += qty;
		total += qty;
		//On affecte la valeur aux composants HTML
		$(id + "HeaderTotal").innerHTML = total;
		$(id + "HeaderCreature").innerHTML = creature;
		$(id + "HeaderLand").innerHTML = land;
	}

	//**** FONCTIONS PUBLIQUES
	this.construct = function(idIft, refCard, trfMenu, trfMenuMode) {
		id = idIft;
		htmlCard = refCard;
		transferMenu = trfMenu;
		transferMenuMode = trfMenuMode;
		compBt_OrderName = "BT_" + id.toUpperCase() + "_ORDERBY_NAME";
		compBt_OrderCost = "BT_" + id.toUpperCase() + "_ORDERBY_COST";
		compBt_OrderType = "BT_" + id.toUpperCase() + "_ORDERBY_TYPE";
		$(compBt_OrderName).onclick = function() { updSortActions(0); sortDeck("NAME"); };
		$(compBt_OrderType).onclick = function() { updSortActions(1); sortDeck("TYPE"); };
		$(compBt_OrderCost).onclick = function() { updSortActions(2); sortDeck("COST"); };
	}

	//Mise à jour de l'interface
	this.update = function(card, qty, mode) {
		switch(mode) {
			case "add" :
				//Ajout de cartes
				pool.push(card);
				addRow(card, qty);
			break;
			case "update" :
				updateRow(card, qty);
			break;
		}
		setDeckHeader(card, qty);
		harmonizeDeck();
	}

	//Mise en conformité de l'alternance de couleur ligne par ligne
	this.harmonize = function() { harmonizeDeck(); }

	//Vide l'interface
	this.empty = function() {
		pool.length = 0;
		//Si le menu de transfert est ouvert, on le ferme
		transferMenu.close();
		emptyDeck();
		resetDeckHeader();
	}


}//Fin de la classe MyDeck_VSDeckMaker

/************************************************************************/
/******************************  |DECK|  ********************************/
/************************************************************************/
MyDeck = function() {
	//**** VARIABLES PRIVÉES
	var tCards = new Array();
	var interface = "";

	//**** VARIABLES PUBLIQUES


	//**** FONCTIONS PRIVÉES :
	//Vérifie si le deck contient une carte
	//Une carte est définie par son nom et par son set.
	var hasCard = function(card) {
		var cardToFind = card.nom + "_" + card.shortset;
		var cardIndex = -1;
		for(var i = 0; i < tCards.length; i++)
		{
			var cardTmp = tCards[i][0];
			if( (cardTmp.nom + "_" + cardTmp.shortset) == cardToFind)
			{
				cardIndex = i;
				break;
			}
		}
		return cardIndex;
	}

	//Met à jour la quantité de la carte
	var updateCardsList = function(card, qty) {
		var newCard = new Array(card, qty);
		var cardIndex = hasCard(card);
		var mode = "";
		//On vérifie si la carte a déja été inséré dans le deck
		if(cardIndex > -1)
		{
			//Si la quantité de la carte est > qty, on augmente la carte d'autant, sinon, on la supprime
			if( tCards[cardIndex][1] + qty > 0)
			 	tCards[cardIndex][1] += qty;
			else
				deleteFromArray(tCards, cardIndex);
			mode = "update";
		}
		else
		{
			tCards.push(newCard);
			mode = "add";
		}
		return mode;
	}

	//**** FONCTIONS PUBLIQUES :
	this.construct = function(refItf) { interface = refItf; }

	this.getCardsList = function() { return tCards; }
	this.getInterface = function() { return interface; }

	//Met à jour les différentes lignes du deck en fonction des événements
	//Ajout, Suppression ou Déplacement de cartes
	this.update = function(card, qty) {
		var correctMode = updateCardsList(card, qty);
		interface.update(card, qty, correctMode);
	}

	//Annule un transfert de carte
	this.cancelTransfert = function() { interface.harmonize();	}

	//Vide le deck
	this.empty = function() { tCards.length = 0; interface.empty();	}

}//Fin de la classe MyDeck

/************************************************************************/
/***********************  |DECK MANIPULATION| ***************************/
/************************************************************************/
MyDeckManipulation = function() {
	//**** VARIABLES PRIVÉES
	var id = "";
	var statsBox = "fullDeckStats";
	var statsCC = "spellByCCost";
	var statsCMana = "spellColoredManaSymbol";
	var statsType = "spellByType";
	var statsColor = "spellByColor";
	//Composants HTML spécifiques
	var compBt_Load = "BT_LOAD_DECK";
	var compCB_Load = "DECK_TO_LOAD";
	var compBt_Save = "BT_SAVE_DECK";
	var compBt_Export = "BT_EXPORT_DECK";
	var compBt_New = "BT_NEW_DECK";
	var compBt_Stats = "BT_SHOW_DECK_STATS";
	var compBt_Stats_Close = "BT_CLOSE_STATS";
	var compBt_Delete = "BT_DELETE_DECK";
	//Fenetre modale
	var saveWin = new MyModalDBox();
	var exportWin = new MyModalDBox();
	var compTxt_DeckName = "TXT_MODAL_DECKNAME";
	var compHd_DeckName = "HD_DECKNAME";
	var compHd_DeckContent = "HD_DECKCONTENT";
	var compHd_SaveMode = "HD_SAVEMODE";
	var userDeckDir = "";
	var box1 = "";
	var box2 = "";

	//**** VARIABLES PUBLIQUES

	//**** FONCTIONS PRIVÉES
	//Créer un nouveau deck
	var newDeck = function() {
	  box1.empty();
	  box2.empty();
	}

	//Charger un deck qui a été sauvegardé
	//Les decks chargés sont des fichiers .JSON
	var loadDeck = function(nomFichier) {
		//On vide le deck
		newDeck();
		//On cache les stats
		hideStats();
		var fichier = "users_decks/" + userDeckDir + "/" + nomFichier + ".json";
		var userdeck = new Array();
		var qty = 0;
		var carte = new Array();
		//On charge le deck
		userdeck = globalBrowser.getJSONData(fichier, false);
		for(var i = 0; i < userdeck.cartes.carte.length; i++)
		{
			carte = userdeck.cartes.carte[i];
			if(carte)
			{
				qty = parseInt(carte.qty);
				if(carte.side == 0)
					box1.update(carte, qty);
				else if(carte.side == 1)
					box2.update(carte, qty);
			}
		}
	}

	// Sauvegarder le deck
	var saveDeck = function() {
		var deckList = box1.getCardsList();
		var sideList = box2.getCardsList();
		var card = "";
		var cardQty = 0;
		//Elements du deck
		var defaultDeckName = "MyDeck";
		var JSONFile = ' {"cartes" : {\n ';
		var dCreaTmp = new Date();
		var dateCreation = (dCreaTmp.getMonth() + 1) + "/" + dCreaTmp.getDate() + "/" + dCreaTmp.getFullYear(); //+ " " +  dCreaTmp.getHours() + ":" + dCreaTmp.getMinutes() + ":" + dCreaTmp.getSeconds();

		//Copyright
		JSONFile += ' "copyright" : {"author": \'Nicolas Castelli\', "email": \'admin@keryas.com\', "createdFrom": \'mtg.keryas.com\', "dateOfCreation": \'' + dateCreation + '\'},\n';
		//Sauvegarde du deck
		JSONFile += ' "carte" : [ \n';
		var i=0
		for(i=0; i < deckList.length; i++)
		{
			card = deckList[i][0];
			cardQty = deckList[i][1];
			JSONFile += '{\n';
			JSONFile += '"nom": \'' + card.nom + '\',\n';
			JSONFile += '"type": \'' + card.type + '\',\n';
			JSONFile += '"soustype": \'' + card.soustype + '\',\n';
			JSONFile += '"cout": \'' + card.cout + '\',\n';
			JSONFile += '"couthtml": \'' + card.couthtml + '\',\n';
			JSONFile += '"valeurcout": \'' + card.valeurcout + '\',\n';
			JSONFile += '"rarete": \'' + card.rarete + '\',\n';
			JSONFile += '"force": \'' + card.force + '\',\n';
			JSONFile += '"endurance": \'' + card.endurance + '\',\n';
			JSONFile += '"ruleshtml": \'' + card.ruleshtml + '\',\n';
			JSONFile += '"nomscan": \'' + card.nomscan + '\',\n';
			JSONFile += '"srcscan": \'' + card.srcscan + '\',\n';
			JSONFile += '"shortset": \'' + card.shortset + '\',\n';
			JSONFile += '"set": \'' + card.set + '\',\n';
			JSONFile += '"qty": \'' + cardQty + '\',\n';
			if(card.nom_lang)
			{
				JSONFile += '"nom_lang": \'' + card.nom_lang + '\',\n';
				JSONFile += '"type_lang": \'' + card.type_lang + '\',\n';
				JSONFile += '"soustype_lang": \'' + card.soustype_lang + '\',\n';
				JSONFile += '"rarete_lang": \'' + card.rarete_lang + '\',\n';
				JSONFile += '"ruleshtml_lang": \'' + card.ruleshtml_lang + '\',\n';
				JSONFile += '"nomscan_lang": \'' + card.nomscan_lang + '\',\n';
				JSONFile += '"srcscan_lang": \'' + card.srcscan_lang + '\',\n';
			}
			JSONFile += '"side": \'0\'\n';
			JSONFile += '},\n';
		}
		//Sauvegarde du side
		for(i=0; i < sideList.length; i++)
		{
			card = sideList[i][0];
			cardQty = sideList[i][1];
			JSONFile += '{\n';
			JSONFile += '"nom": \'' + card.nom + '\',\n';
			JSONFile += '"type": \'' + card.type + '\',\n';
			JSONFile += '"soustype": \'' + card.soustype + '\',\n';
			JSONFile += '"cout": \'' + card.cout + '\',\n';
			JSONFile += '"couthtml": \'' + card.couthtml + '\',\n';
			JSONFile += '"valeurcout": \'' + card.valeurcout + '\',\n';
			JSONFile += '"rarete": \'' + card.rarete + '\',\n';
			JSONFile += '"force": \'' + card.force + '\',\n';
			JSONFile += '"endurance": \'' + card.endurance + '\',\n';
			JSONFile += '"ruleshtml": \'' + card.ruleshtml + '\',\n';
			JSONFile += '"nomscan": \'' + card.nomscan + '\',\n';
			JSONFile += '"srcscan": \'' + card.srcscan + '\',\n';
			JSONFile += '"shortset": \'' + card.shortset + '\',\n';
			JSONFile += '"set": \'' + card.set + '\',\n';
			JSONFile += '"qty": \'' + cardQty + '\',\n';
			if(card.nom_lang)
			{
				JSONFile += '"nom_lang": \'' + card.nom_lang + '\',\n';
				JSONFile += '"type_lang": \'' + card.type_lang + '\',\n';
				JSONFile += '"soustype_lang": \'' + card.soustype_lang + '\',\n';
				JSONFile += '"rarete_lang": \'' + card.rarete_lang + '\',\n';
				JSONFile += '"ruleshtml_lang": \'' + card.ruleshtml_lang + '\',\n';
				JSONFile += '"nomscan_lang": \'' + card.nomscan_lang + '\',\n';
				JSONFile += '"srcscan_lang": \'' + card.srcscan_lang + '\',\n';
			}
			JSONFile += '"side": \'1\'\n';
			JSONFile += '},\n';
		}

		JSONFile = JSONFile.substr(0, JSONFile.length - 2);
	  JSONFile += '\n]\n}\n}';
	  //Si le fichier JSON à créer contient bien quelque chose, on lance la sauvegarde
	  if( (deckList[0] != null) || (sideList[0]  != null))
	  {
	  	//Si un deck a été chargé, on donne son nom au deck à sauvegarder.
	  	if($(compCB_Load))
	  		defaultDeckName = $(compCB_Load).options[$(compCB_Load).selectedIndex].innerHTML;
      //On donne un nom par défaut au deck
      $(compTxt_DeckName).value = defaultDeckName;
      $(compHd_DeckContent).value = JSONFile;
			$(compHd_SaveMode).value = "SAVE_USER_DECK";
      //Fenetre modale pour le deck
      saveWin.showModal(compBt_Save);
		}
	}

	//Pour exporter le deck : fait apparaître une fenetre modale
	var exportDeck = function() {
		var deckContent = "";
		var deckName = $(compCB_Load).options[$(compCB_Load).selectedIndex].innerHTML;
		var fichier = "users_decks/" + userDeckDir + "/" + deckName + ".json";
		var userdeck = new Array();
		var qty = 0;
		var carte = new Array();
		//On charge le deck en mémoire pour l'exporter
		userdeck = globalBrowser.getJSONData(fichier, false);
		for(var i = 0; i < userdeck.cartes.carte.length; i++)
		{
			carte = userdeck.cartes.carte[i];
			qty = parseInt(carte.qty);
			if(carte.side == 0)
				deckContent += "deck:" + carte.nom.replace(/&apos;/gi, "'") + ":" + carte.type + ":" + carte.shortset + ":" + qty;
			else if(carte.side == 1)
				deckContent += "side:" + carte.nom.replace(/&apos;/gi, "'") + ":" + carte.type + ":" + carte.shortset + ":" + qty;
			//Pour indiquer qu'on change de carte, on met un "#"
			deckContent += "#";
		}
		//Le fichier est prêt à être exporté
		$("MODAL_EXPORT_DECKNAME").innerHTML = " " + deckName + " ";
		$(compHd_DeckName).value = deckName;
		$(compHd_DeckContent).value = deckContent;
		$(compHd_SaveMode).value = "EXPORT_USER_DECK";
		//Fenetre modale pour le deck
    exportWin.showModal(compBt_Save);
	}

	//21/11/2009 Pour supprimer un deck sauvegardé
	var deleteDeck = function() {
		var deckName = $(compCB_Load).options[$(compCB_Load).selectedIndex].innerHTML;
		var fichier = "users_decks/" + userDeckDir + "/" + deckName + ".json";
		var confimMsg = $("HD_MSG_DELETE").value  + deckName + " ?" //Contient le message de validation
		if(confirm(confimMsg))
		{
			$(compHd_DeckName).value = deckName;
			$(compHd_SaveMode).value = "DELETE_USER_DECK";
			submitForm('formDeck');
		}
	}

	//*********************** CALCUL DE STATS ************************//
	//Pour cacher la fenêtre de stats
	var hideStats = function(idTable) { $(statsBox).className = "none"; }

	//Pour afficher la fenêtre de stats
	var showStats = function(evt) {
		var tPoolStat1 = box1.getCardsList();
		var arrTmp = new Array();
		initStats(statsCC, 3);
		initStats(statsCMana, 2);
		initStats(statsType, 3);
		initStats(statsColor, 3);
		//Stats du deck
		arrTmp = getSpellsByCC(tPoolStat1);
		setStatsByCC(arrTmp);
		arrTmp = getSpellsByColoredManaSymbol(tPoolStat1);
		setStatsByCMana(arrTmp);
		arrTmp = getSpellsByType(tPoolStat1);
		setStatsByType(arrTmp);
		arrTmp = getSpellsByColor(tPoolStat1);
		setStatsByColor(arrTmp);
		//Stats du side
		tPoolStat1 = box2.getCardsList();
		arrTmp = getSpellsByCC(tPoolStat1);
		setStatsByCC(arrTmp);
		arrTmp = getSpellsByColoredManaSymbol(tPoolStat1);
		setStatsByCMana(arrTmp);
		arrTmp = getSpellsByType(tPoolStat1);
		setStatsByType(arrTmp);
		arrTmp = getSpellsByColor(tPoolStat1);
		setStatsByColor(arrTmp);

		//On affiche les stats
		displayStats(evt);
	}

	//Affiche la div des stats
	var displayStats = function(evt) {
		var XY = getWindowPos();
		var xPos = XY[0];
		var yPos = XY[1];
		//Affichage des statistiques
		$(statsBox).style.top = yPos + 'px';
		$(statsBox).style.left = xPos + 'px';
		($(statsBox).className == "none") ? $(statsBox).className = "" : $(statsBox).className = "none";
	}

	//Calcule la position de la fenetre de stats en fonction du navigateur
	var getWindowPos = function() {
		var xPos = $(compBt_Save).offsetLeft - 270;
		var yPos = $(compBt_Save).offsetTop - 295;
		//Evidemment, spécifique pour IE qui fait rien comme les autres
		if(globalBrowser.navigator == "Internet Explorer")
		{
			xPos = $(compBt_Save).offsetLeft - 130;
			yPos = $(compBt_Save).offsetTop + 230;
			/*
			//IE6
			if(globalBrowser.navVersion == 6)
			{
				yPos = yPos + 200;
				xPos = $(idAnchor).offsetLeft 2 30;
			}
			//IE7 et au-delà
			else if(globalBrowser.navVersion >= 7)
			{
				yPos = yPos + 150;
				xPos = $(idAnchor).offsetLeft*2.7;
			}
			*/
		}
		var arrPos = new Array(xPos, yPos);
		return arrPos;
	}

	//Vide les tableaux de stats
	var initStats = function(idArr, limitRow) {
		//On remet à 0 les 2 dernières lignes du tableau
		var nbRows = $(idArr).rows.length;
		for(var i=nbRows-1; i > nbRows-limitRow; i--)
		{
			var row = $(idArr).rows[i];
			for(var j = 0; j < row.cells.length; j++)
			{
				row.cells[j].innerHTML = 0;
			}
		}
	}

	//************ MANA CURVE *************//
	//Pour calculer la mana curve
	var getSpellsByCC = function(pool) {
		var card = "";
		var cardQty = 0;
		var cardCC = 0;
		var totalCost = 0;
		var nbSpells = 0;
		var stats = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
		for(var i=0; i < pool.length; i++)
		{
			card = pool[i][0];
			cardQty = pool[i][1];
			//On ne doit pas prendre en compte les terrains !
			if(!(card.type.hasWord("Land")))
			{
				if(parseInt(card.valeurcout) > 10)
					cardCC = 10;
				else
					cardCC = parseInt(card.valeurcout);
				//Nombre de cartes par coût
				stats[cardCC] = stats[cardCC] + cardQty;
				totalCost += cardCC*cardQty;
				nbSpells += cardQty;
			}
		}

		if(nbSpells != 0)
		{
			stats[11] = totalCost;
			stats[12] = nbSpells;
		}
		return stats;
	}

	//Pour écrire les stats du deck
	var setStatsByCC = function(arr) {
		var qty = 0;
		var avgCost = 0;
		for(var i=0; i < arr.length-2; i++)
		{
			qty = parseInt($(statsCC).rows[3].cells[i].innerHTML);
			$(statsCC).rows[3].cells[i].innerHTML = qty + arr[i];
		}
		qty = parseInt($(statsCC).rows[4].cells[0].innerHTML);
		$(statsCC).rows[4].cells[0].innerHTML = qty + arr[11];
		qty = parseInt($(statsCC).rows[4].cells[1].innerHTML);
		$(statsCC).rows[4].cells[1].innerHTML = qty + arr[12];
		avgCost = parseInt($(statsCC).rows[4].cells[0].innerHTML) / parseInt($(statsCC).rows[4].cells[1].innerHTML);
		if(isNaN(avgCost))
			avgCost = 0;
		$(statsCC).rows[4].cells[2].innerHTML = (Math.round(avgCost*100))/100;
	}

	//************ COLOR SYMBOL *************//
	//Pour calculer le nombre de symboles colorés dans le deck
	var getSpellsByColoredManaSymbol = function(pool) {
		var card = "";
		var cardQty = 0;
		var coutTmp = "";
		var stats = new Array(0, 0, 0, 0, 0); //WRGUB
		for(var i=0; i < pool.length; i++)
		{
			card = pool[i][0];
			cardQty = pool[i][1];
			//On ne doit pas prendre en compte les terrains !
			if(!(card.type.hasWord("Land")))
			{
				coutTmp = card.cout;
				//On décortique le coût pour identifier les symboles colorés
				//A chaque fois qu'on trouve une des lettres W,R,U,G,B
				//on ajoute +1 à la colonne correspondant à ce coût. Sinon on ne fait rien.
				//Pour les coûts hybrides, comment je fais ? A voir dans MTGO. Par défaut,
				//il compte les 2.
				for(var j=0; j < coutTmp.length; j++)
				{
					if(coutTmp.charAt(j) == "W")
						stats[0] = stats[0] + cardQty;
					else if(coutTmp.charAt(j) == "R")
						stats[1] = stats[1] + cardQty;
					else if(coutTmp.charAt(j) == "G")
						stats[2] = stats[2] + cardQty;
					else if(coutTmp.charAt(j) == "U")
						stats[3] = stats[3] + cardQty;
					else if(coutTmp.charAt(j) == "B")
						stats[4] = stats[4] + cardQty;
				}
			}
		}
		return stats;
	}

	//Pour écrire les stats du deck
	var setStatsByCMana = function(arr) {
		var qty = 0;
		for(var i=0; i < arr.length; i++)
		{
			qty = parseInt($(statsCMana).rows[2].cells[i].innerHTML);
			$(statsCMana).rows[2].cells[i].innerHTML = qty + arr[i];
		}
	}

	//************ BY TYPE *************//
	//Pour calculer le nombre de sorts par type de cartes
	var getSpellsByType = function(pool) {
		var card = "";
		var cardQty = 0;
		var nbCards = 0;
		var stats = new Array(0, 0, 0, 0, 0, 0, 0, 0);

		for(var i=0; i < pool.length; i++)
		{
			card = pool[i][0];
			cardQty = pool[i][1];
			nbCards += cardQty;
			if(card.type.toUpperCase().hasWord("LAND"))
				stats[0] = stats[0] + cardQty;
			if(card.type.toUpperCase().hasWord("ARTIFACT"))
				stats[1] = stats[1] + cardQty;
			if(card.type.toUpperCase().hasWord("CREATURE"))
				stats[2] = stats[2] + cardQty;
			if(card.type.toUpperCase().hasWord("INSTANT"))
				stats[3] = stats[3] + cardQty;
			if(card.type.toUpperCase().hasWord("SORCERY"))
				stats[4] = stats[4] + cardQty;
			if(card.type.toUpperCase().hasWord("ENCHANTMENT"))
				stats[5] = stats[5] + cardQty;
			if(card.type.toUpperCase().hasWord("PLANESWALKER"))
				stats[6] = stats[6] + cardQty;
		}
		stats[7] = nbCards;
		return stats;
	}

	//Pour écrire les stats du deck
	var setStatsByType = function(arr) {
		var qty = 0;
		var total = 0;
		var valPcent = 0;
		//Une boucle pour les valeurs
		for(var i=0; i < arr.length; i++)
		{
			qty = parseInt($(statsType).rows[2].cells[i].innerHTML);
			$(statsType).rows[2].cells[i].innerHTML = qty + arr[i];
		}
		//Une boucle pour les pourcentages
		for(var i=0; i < arr.length; i++)
		{
			qty = parseInt($(statsType).rows[2].cells[i].innerHTML);
			total = parseInt($(statsType).rows[2].cells[7].innerHTML);
			if(total != 0)
				valPcent = qty/total;
			$(statsType).rows[3].cells[i].innerHTML = ((Math.round(valPcent*10))/10)*100 + "%";
		}
	}



	//************ BY COLOR *************//
	//Pour calculer le nombre de sorts par couleur
	var getSpellsByColor = function(pool) {
		var card = "";
		var cardQty = 0;
		var nbCards = 0;
		var stats = new Array(0, 0, 0, 0, 0, 0, 0, 0);

		// On compte le nombre de sorts par couleur
		// Pour cela, on décortique le coût de chaque carte pour identifier les symboles colorés
		// A chaque fois qu'on trouve une des lettres W,R,U,G,B
		// on ajoute +1 à la colonne correspondant à ce coût. Sinon on ne fait rien.
		// Pour les coûts hybrides, comment je fais ? A voir dans MTGO. Par défaut,
		// il compte les 2.
		//D'abord le deck
		for(var i=0; i < pool.length; i++)
		{
			card = pool[i][0];
			cardQty = pool[i][1];
			//On ne doit pas prendre en compte les terrains !
			if(!(card.type.hasWord("Land")))
			{
				nbCards += cardQty;
				//La carte est-elle multicolore ?
				if( isMulticolor(card.cout))
					stats[6] = stats[6] + cardQty;
				else
				{
					if(card.cout.toUpperCase().hasChar("W"))
						stats[0] = stats[0] + cardQty;
					if(card.cout.toUpperCase().hasChar("R"))
						stats[1] = stats[1] + cardQty;
					if(card.cout.toUpperCase().hasChar("G"))
						stats[2] = stats[2] + cardQty;
					if(card.cout.toUpperCase().hasChar("U"))
						stats[3] = stats[3] + cardQty;
					if(card.cout.toUpperCase().hasChar("B"))
						stats[4] = stats[4] + cardQty;
					if(!card.cout.toUpperCase().hasChar("WRGUB"))
						stats[5] = stats[5] + cardQty;
				}
			}
		}
		stats[7] = nbCards;
		return stats;
	}

	//Pour vérifier si la carte est multicolore
	var isMulticolor = function(cout) {
		var itIs = false;
		if(cout.hasChar("W") && cout.hasChar("RGUB") ||
			 cout.hasChar("R") && cout.hasChar("WGUB") ||
			 cout.hasChar("G") && cout.hasChar("WRUB") ||
			 cout.hasChar("U") && cout.hasChar("WRGB") ||
			 cout.hasChar("B") && cout.hasChar("WRGU")
			)
		{
			itIs = true;
		}
		return itIs;
	}

	//Pour écrire les stats du deck
	var setStatsByColor = function(arr) {
		var qty = 0;
		var total = 0;
		var valPcent = 0;
		//Une boucle pour les valeurs
		for(var i=0; i < arr.length; i++)
		{
			qty = parseInt($(statsColor).rows[2].cells[i].innerHTML);
			$(statsColor).rows[2].cells[i].innerHTML = qty + arr[i];
		}
		//Une boucle pour les pourcentages
		for(var i=0; i < arr.length; i++)
		{
			qty = parseInt($(statsColor).rows[2].cells[i].innerHTML);
			total = parseInt($(statsColor).rows[2].cells[7].innerHTML);
			if(total != 0)
				valPcent = qty/total;
			$(statsColor).rows[3].cells[i].innerHTML = ((Math.round(valPcent*10))/10)*100 + "%";
		}
	}


	//**** FONCTIONS PUBLIQUES
	this.construct = function(idElt, refDeck, refSide, userDeckRep) {
		id = idElt;
		box1 = refDeck;
		box2 = refSide;
		userDeckDir = userDeckRep;
		//Initialisation des fenetres modales
		saveWin.construct("MODAL_SAVE");
		exportWin.construct("MODAL_EXPORT");
		//Initialisation des boutons
		$(compBt_Save).onclick = function() { saveDeck(); };
		$(compBt_Export).onclick = function() { exportDeck(); };
		$(compBt_New).onclick = function() { newDeck(); };
		$(compBt_Delete).onclick = function() { deleteDeck(); };
		if (globalBrowser.getNavigator() == "Internet Explorer" )
			$(compBt_Stats).onclick = function() { showStats(event); };
		else
			$(compBt_Stats).onclick = function(event) { showStats(event); };
		//Si l'utilisateur n'est pas connecté, pas de boutons pour cacher les stats
		if($(compBt_Stats_Close))
			$(compBt_Stats_Close).onclick = function() { hideStats(); };
		//Si aucun deck n'est crée, le bouton de chargement n'apparaît pas
		if($(compBt_Load))
			$(compBt_Load).onclick = function() { var deckName = $(compCB_Load).options[$(compCB_Load).selectedIndex].innerHTML; loadDeck(deckName); };
	}

}// Fin de la classe MyDeckManipulation

