// Copyright (C) 2008 SpinkBB
// Entire code by Julien VAUBOURG
// julien__AT__vaubourg__DOT__com

// Author  : http://julien.vaubourg.com
// SpinkBB : http://spinkbb.jsand.net
// Forums  : http://CtrlAltSuppr.com

ImportExport = {
	httpr: '',
	idSession: null,

	/** Création de GArrayStyles */
	createGArrayStyles: function(serialize) {
		EditStyle.GArrayStyles = new Array();

		if(Outils.empty(serialize)) {
			alert(Langues.get('Session vide ou inexistante.'));
			return false;
		}

		var arrayStyles = ImportExport.deserializer(serialize);
		arrayStyles = ImportExport.desoptimiser(arrayStyles);
		ImportExport.importStyle(arrayStyles);
	},

	/** Création de GArrayStyles depuis la session */
	importFromSession: function() {
		if(ImportExport.issetCookie(Parametres.idScript + '_session')) {
			if(Outils.empty(ImportExport.idSession))
				ImportExport.idSession = ImportExport.lireCookie(Parametres.idScript + '_session');

			ImportExport.httpr += 'ImportExport.createGArrayStyles(retour);';
			ImportExport.session('lire');
		} else
			EditStyle.GArrayStyles = new Array();
	},

	/** Création de GArrayStyles depuis la session (preview uniquement) */
	importFromPreview: function(idPreview) {
		ImportExport.idSession = idPreview;
		ImportExport.httpr += 'ImportExport.createGArrayStyles(retour);';
		ImportExport.session('lirePreview');
	},

	/** Création des régles CSS depuis GArrayStyles */
	importStyle: function(arrayStyles) {

		// Selecteurs
		for(var selecteur in arrayStyles)
			if(!Outils.isFunction(arrayStyles[selecteur])) {
				EditStyle.createRule(selecteur);

				// Propriétés
				for(var propriete in arrayStyles[selecteur])
					if(!Outils.isFunction(arrayStyles[selecteur][propriete]) && propriete != 'cssRule')
						EditStyle.updateRule(selecteur, propriete, arrayStyles[selecteur][propriete]);
			}
	},

	/** Enregistrer les modifications effectuées dans la session */
	saveInSession: function() {
		var arrayStyles = ImportExport.optimiser(EditStyle.GArrayStyles);
		var serialize = ImportExport.serializer(arrayStyles);

		if(!Outils.empty(serialize)) {
			if(!ImportExport.issetCookie(Parametres.idScript + '_session'))
				ImportExport.httpr += 'ImportExport.creerCookie(Parametres.idScript + \'_session\', retour); ImportExport.idSession = retour;';

			ImportExport.session('ecrire', serialize);
			Outils.change = false;
			
			return true;
		}

		return false;
	},

	/** Sérialization maison de GArrayStyles */
	serializer: function(arrayStyles) {
		var serialize = '';

		// Selecteurs
		for(var selecteur in arrayStyles)
			if(!Outils.isFunction(arrayStyles[selecteur])) {
				serialize += selecteur + '{';
		
				// Propriétés
				for(var propriete in arrayStyles[selecteur])
					if(!Outils.isFunction(arrayStyles[selecteur][propriete]) && propriete != 'cssRule')
						serialize += propriete + ':' + arrayStyles[selecteur][propriete] + ';';

				serialize = serialize.substring(0, serialize.length-1);
				serialize += '}';
			}

		return serialize;
	},

	/** Formation de GArrayStyles */
	deserializer: function(serialize) {
		var arrayStyles = new Array();

		if(!Outils.empty(serialize)) {
			var blocks = serialize.split(/}/g);

			// Suppression du dernier élément (si pas IE)
			if(Outils.isset(blocks[blocks.length - 1])) {
				if(blocks[blocks.length - 1].length == 0)
					blocks.pop();
			} else
				alert(Langues.get('Erreur de d\351s\351rialisation !'));

			// Sélecteurs
			for(var i = 0; i < blocks.length; i++) {
				var separation = blocks[i].split('{');

				var selecteur = separation[0];
				var valeurs = separation[1].split(/;/g);

				// Nouvelle entrée dans GArrayStyles
				arrayStyles[selecteur] = new Array();
				arrayStyles[selecteur]['cssRule'] = null;

				// Ajout des propriétés
				for(var j = 0; j < valeurs.length; j++) {
					var couple = valeurs[j].split(':');
					arrayStyles[selecteur][couple[0]] = couple[1];
				}
			}
		}
		
		return arrayStyles;
	},

	/** Optimisation de GArrayStyles */	
	optimiser: function(arrayStyles) {
		var newArrayStyles = {};

		// Copie des propriétés de l'objet (et petites optimisations)
		for(var selecteur in arrayStyles)
			if(!Outils.isFunction(arrayStyles[selecteur])) {
				if(!Outils.isset(newArrayStyles[selecteur]))
					newArrayStyles[selecteur] = {};
			
				for(var propriete in arrayStyles[selecteur])
					if(!Outils.isFunction(arrayStyles[selecteur][propriete]) && propriete != 'cssRule') {
						newArrayStyles[selecteur][propriete] = /^0[A-Z]{2}$/i.test(arrayStyles[selecteur][propriete]) ? '0' : arrayStyles[selecteur][propriete];

						// Hexa sur 3 caractères
						if(newArrayStyles[selecteur][propriete].substr(0,1) == '#'
							&& newArrayStyles[selecteur][propriete].substr(1,1) == newArrayStyles[selecteur][propriete].substr(2,1)
							&& newArrayStyles[selecteur][propriete].substr(3,1) == newArrayStyles[selecteur][propriete].substr(4,1)
							&& newArrayStyles[selecteur][propriete].substr(5,1) == newArrayStyles[selecteur][propriete].substr(6,1)
						)
							newArrayStyles[selecteur][propriete] = '#' + newArrayStyles[selecteur][propriete].substr(1,1) + newArrayStyles[selecteur][propriete].substr(3,1) + newArrayStyles[selecteur][propriete].substr(5,1);
					}
			}

		// Utilisation de la copie
		arrayStyles = newArrayStyles;

		// Elements à fusionner
		var fusionsCard = [
			'border-4c-style',
			'border-4c-width',
			'border-4c-color',
			'padding-4c',
			'margin-4c'
		];

		var card = ['top', 'right', 'bottom', 'left'];
		var propBorder = ['width', 'style', 'color'];
		var condensats = {};

		// Sélecteurs
		for(var selecteur in arrayStyles)
			if(!Outils.isFunction(arrayStyles[selecteur])) {


				/** Fusion des border-[card]-[prop] en border-[prop] **/

				for(var fc = 0; fc < fusionsCard.length; fc++) {
					var elementsCard = new Array();

					// Création des 4 éléments
					for(var c= 0; c < card.length; c++)
						elementsCard[c] = fusionsCard[fc].replace('4c', card[c]);

					// Si les 4 côtés ont été redéfinis
					if(	Outils.isset(arrayStyles[selecteur][elementsCard[0]]) &&
						Outils.isset(arrayStyles[selecteur][elementsCard[1]]) &&
						Outils.isset(arrayStyles[selecteur][elementsCard[2]]) &&
						Outils.isset(arrayStyles[selecteur][elementsCard[3]]) ) {

						// Si les valeurs des côtés sont au moins égales par paires
						if(	arrayStyles[selecteur][elementsCard[0]] == arrayStyles[selecteur][elementsCard[2]] &&
							arrayStyles[selecteur][elementsCard[1]] == arrayStyles[selecteur][elementsCard[3]] ) {

							// Si elles le sont toutes, fusion en une seule valeur
							if(arrayStyles[selecteur][elementsCard[0]] == arrayStyles[selecteur][elementsCard[1]])
								arrayStyles[selecteur][fusionsCard[fc].replace('-4c', '')] = arrayStyles[selecteur][elementsCard[0]];

							// Sinon fusion en deux valeurs
							else
								arrayStyles[selecteur][fusionsCard[fc].replace('-4c', '')] = arrayStyles[selecteur][elementsCard[0]] + ' ' + arrayStyles[selecteur][elementsCard[1]];

						// Autrement, rassemblement des 4 valeurs sans fusion
						} else
							arrayStyles[selecteur][fusionsCard[fc].replace('-4c', '')] = arrayStyles[selecteur][elementsCard[0]] + ' ' + arrayStyles[selecteur][elementsCard[1]] + ' ' + arrayStyles[selecteur][elementsCard[2]] + ' ' + arrayStyles[selecteur][elementsCard[3]];

						// Suppression des valeurs qui ont été fusionnées en une seule
						delete arrayStyles[selecteur][elementsCard[0]];
						delete arrayStyles[selecteur][elementsCard[1]];
						delete arrayStyles[selecteur][elementsCard[2]];
						delete arrayStyles[selecteur][elementsCard[3]];
					}
				}


				/** Fusion des border-[prop] complets en border**/
				
				var fusion = true;
				for(var p = 0; p < propBorder.length && fusion; fusion = Outils.isset(arrayStyles[selecteur]['border-' + propBorder[p]]) && !arrayStyles[selecteur]['border-' + propBorder[p]].match(' '), p++);

				// Si les 3 propriétés du border sont définies (== ont été fusionnées) et qu'elle ne contiennent pas plus d'une valeur (== les 4 côtés égaux), alors fusion du tout
				if(fusion) {
					arrayStyles[selecteur]['border'] = arrayStyles[selecteur]['border-width'] + ' ' + arrayStyles[selecteur]['border-style'] + ' ' + arrayStyles[selecteur]['border-color'];
					for(var p = 0; p < propBorder.length; delete arrayStyles[selecteur]['border-' + propBorder[p++]]);
				}


				/** Fusion des border-[card]-[prop] en border-[card] **/

				for(var c = 0; c < card.length; c++) {

					// Si les propriétés du border pour une cardinalités ont été définies
					if(	Outils.isset(arrayStyles[selecteur]['border-' + card[c] + '-width']) &&
						Outils.isset(arrayStyles[selecteur]['border-' + card[c] + '-style']) &&
						Outils.isset(arrayStyles[selecteur]['border-' + card[c] + '-color']) ) {

						// Alors fusion en une seule (border-4c)
						arrayStyles[selecteur]['border-' + card[c]] = arrayStyles[selecteur]['border-' + card[c] + '-width'] + ' ' + arrayStyles[selecteur]['border-' + card[c] + '-style'] + ' ' + arrayStyles[selecteur]['border-' + card[c] + '-color'];
						for(var p = 0; p < propBorder.length; delete arrayStyles[selecteur]['border-' + card[c] + '-' + propBorder[p++]]);
					}
				}
				
				
				/** Fusion des blocks identiques **/
				var condensat = new Array();
				
				// Création du condensat (sorte de serialization) du block courant
				for(var propriete in arrayStyles[selecteur])
					if(!Outils.isFunction(arrayStyles[selecteur][propriete]))
						condensat[condensat.length] = propriete + ('' + arrayStyles[selecteur][propriete]).replace(' ', '');

				condensat = Outils.sortTab(condensat).join('');

				// Si le condensat existe déjà, fusion avec l'autre block
				if(Outils.isset(condensats[condensat])) {
					var selecteurIdentique = condensats[condensat];
					condensats[condensat] += ',' + selecteur;
					arrayStyles[condensats[condensat]] = {};
					
					// Copie des propriétés de l'ancien block correspondant pour créer le nouveau
					for(var propriete in arrayStyles[selecteurIdentique])
						if(!Outils.isFunction(arrayStyles[selecteurIdentique][propriete]))
							arrayStyles[condensats[condensat]][propriete] = arrayStyles[selecteurIdentique][propriete];

					// Suppression des blocks qui ont été fusionnés
					arrayStyles[selecteur] = null;
					arrayStyles[selecteurIdentique] = null;
					delete arrayStyles[selecteur];
					delete arrayStyles[selecteurIdentique];

				// Sinon ajout du condensat
				} else
					condensats[condensat] = selecteur;
			}

		return arrayStyles;
	},
	
	/** Désoptimiser GArrayStyles */
	desoptimiser: function(arrayStyles) {
		var newArrayStyles = {};
		var modifications;

		var card = ['top', 'right', 'bottom', 'left'];
		var regBorderProp = new RegExp('-(width|style|color)', 'i');		

		// Sélecteurs
		for(var selecteur in arrayStyles)
			if(!Outils.isFunction(arrayStyles[selecteur])) {
				modifications = {};

				// Propriétés
				for(var propriete in arrayStyles[selecteur])
					if(!Outils.isFunction(arrayStyles[selecteur][propriete]) && propriete != 'cssRule') {

						// Séparation des border-[card]: width style color					
						if(/^border-?(top|right|bottom|left)?$/i.test(propriete) && /^[0-9A-Z]+ [A-Z]+ #?[0-9A-Z]+$/i.test(arrayStyles[selecteur][propriete])) {
							var valeurs = arrayStyles[selecteur][propriete].split(/ /g);
							
							modifications[propriete + '-width'] = valeurs[0];
							modifications[propriete + '-style'] = valeurs[1];
							modifications[propriete + '-color'] = valeurs[2];

						// Séparation des valeurs groupées pour les côtés (les 4, par paires, ou une seule pour tous)
						} else if(/^(margin|padding|border-(width|style|color))$/i.test(propriete)) {
							var valeurs = arrayStyles[selecteur][propriete].split(/ /g);
							var nom = propriete.match('-') ? propriete.replace('-', '-?-') : propriete + '-?';

							// Les quatres côtés sont renseignés à la suite
							if(valeurs.length == 4) {
								for(var c = 0; c < card.length; c++)
									modifications[nom.replace('?', card[c])] = valeurs[c];

							// Les valeurs sont par paires
							} else if(valeurs.length == 2) {
								for(var c = 0; c < card.length; c++)
									modifications[nom.replace('?', card[c])] = valeurs[c%2];

							// Une seule valeur pour les 4 côtés
							} else if(valeurs.length == 1)
								for(var c = 0; c < card.length; c++)
									modifications[nom.replace('?', card[c])] = valeurs[0];

						// Sinon ajout simple de la propriété dans le nouveau tableau
						} else
							modifications[propriete] = arrayStyles[selecteur][propriete];
					}

				var selecteurs = selecteur.split(/,/g);

				// Ajout des propriétés pour chaque sélecteur		
				for(var s = 0; s < selecteurs.length; s++) {
					newArrayStyles[selecteurs[s]] = {};
			
					// Propriétés
					for(var prop in modifications)
						if(!Outils.isFunction(modifications[prop]))
							newArrayStyles[selecteurs[s]][prop] = (prop == 'cssRule') ? modifications[prop] : Outils.setGeneric(modifications[prop]);
				}
			}

		return newArrayStyles;
	},

	/** Formatage du serialize pour la lisibilité */
	readable: function(serialize) {
		var readable = '';
		var selecteurs = serialize.split(/}/g);
		
		if(Outils.isset(selecteurs[selecteurs.length - 1]) && selecteurs[selecteurs.length - 1].length == 0)
			selecteurs.pop();

		// Parcours des sélecteurs
		for(var s = 0; s < selecteurs.length; s++) {
			var separation = selecteurs[s].split(/{/g);
			var proprietes = separation[1].split(/;/);
			
			readable += separation[0].replace(/,/g, ',\n') + ' {\n';
			
			// Parcours des propriétés
			for(var p = 0; p < proprietes.length; p++)
				readable += '\t' + proprietes[p].replace(':', ': ') + ';\n';
				
			readable += '}\n\n';
		}
		
		return readable.substr(0, readable.length - 2);
	},
	
	/** Suppression du formatage pour la lisibilité */
	unreadable: function(serialize) {
		// Suppression des retours à la ligne et des tabulations
		serialize = serialize.replace(/[\n\r\t]+| {2,}/g, '').replace(/ ?;?} ?/g, '}').replace(/ ?: ?/g, ':').replace(/ ?; ?/g, ';').replace(/ ?{ ?/g, '{');
		
		// Suppression des commentaires CSS
		serialize = serialize.replace(/\/\*(.*?)\*\//g, '');

		return serialize;
	},
	
	/** Création de cookie */
	creerCookie: function(nom, valeur, temps /* fac */) {
		if(!Outils.isset(temps) || temps) {
			var expDate = new Date();
			expDate.setTime(expDate.getTime() + (Outils.isset(temps) ? temps : 12*30*24*3600*1000));
			expDate = ';expires=' + expDate.toGMTString();
		} else
			expDate = ''; // Cookie de session

		document.cookie = nom + '=' + escape(valeur) + expDate + ';path=/';
	},
	
	/** Suppression de cookie */
	supprimerCookie: function(nom) {
		var expDate = new Date();
		expDate.setTime(expDate.getTime() - 1);
		document.cookie = nom + '=null;expires=' + expDate.toGMTString() + ';path=/';
	},

	/** Lecture de cookie */
	lireCookie: function(nom) {
		return unescape(((new RegExp(nom + '=' + '([^;]*)')).exec(document.cookie))[1]);
	},

	/** Le cookie existe-t-il ? */
	issetCookie: function(nom) {
		return (new RegExp(nom + '=')).test(document.cookie);
	},

	/** Encodage URL */
	urlencode: function(texte) {
		texte = texte.replace(/[ ]/g,'+');
		return escape(texte);
	},

	/** Lecture/Ecriture dans la session PHP */
	session: function(action, valeur /* fac */) {
		var session = window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : null);

		// Préparation
		session.open('POST', Parametres.root + 'session.php', true);
		session.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

		// Réception
		session.onreadystatechange = function() {
			if(session.readyState < 4)
				Outils.patientez('spkPatientez');

			if(session.readyState == 4) {
				document.getElementById('spkPatientez').style.display = 'none';
				var retour = session.responseText;

				if(/^ERREUR: /.test(retour))
					throw new Error(retour);

				if(!Outils.empty(ImportExport.httpr))
					eval(ImportExport.httpr);

				ImportExport.httpr = '';
			}
		};

		// Envoi
		session.send((!Outils.empty(ImportExport.idSession) ? 'session=' + ImportExport.idSession + '&' : '') + 'script=' + Parametres.idScript + '&' + action + '=' + ((action == 'ecrire') ? ImportExport.urlencode(valeur) : '1'));
	}
};

