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

// Specials thanks to : 
// Jonas John (dec2hex : http://www.jonasjohn.de)
// John Dyer (ColorPicker : http://johndyer.name)


/************************/
/** Méthodes de classe **/
/************************/

Outils = {

	historique: new Array(),
	historiquePointer: -1,
	historiqueChange: false,
	change: false,

	/** * Le flotteur est l'élément de l'arborescence sur lequel l'utilisateur a voulu cliquer
		* Seul cet élément aura une action, le reste des onmousedowns déclenchés par profondeur
		* ne servira à rien.
	*/
	whoIsFlotteur: function(e) {
		if(Outils.flotteur == undefined) {
			Outils.flotteur = this;

			if(Outils.potentialFlotteur != undefined && Outils.potentialFlotteur != false)
				EditStyle.setVisible(false);

			// OnMouseDown déclenché sans clic (navigateur de noeuds)
			if(Outils.isset(Outils.coordonnees)) {
				Outils.flotteur.coordonnees = [Outils.coordonnees[0], Outils.coordonnees[1]];
				delete Outils.coordonnees;
			} else
				Outils.flotteur.coordonnees = Outils.cooMouse(e);

			spinkeur = new EditStyle(Outils.flotteur);
			
			if(!Outils.historiqueChange) {
				if(Outils.historiquePointer != Outils.historique.length - 1)
					Outils.historique = Outils.historique.slice(0, Outils.historiquePointer + 1);
			
				Outils.historique.push(Outils.flotteur);
				Outils.historiquePointer = Outils.historique.length - 1;
			} else
				Outils.historiqueChange = false;

			spinkeur.setVisible();
			spinkeur.creerMenu();
		}
	},

	/** Matérialise le flotchamp.jsNameteur potentiel au survol */
	whoIsPotentialFlotteur: function() {
		if(Outils.flotteur == undefined && (Outils.potentialFlotteur == undefined || Outils.potentialFlotteur == false)) {
			Outils.potentialFlotteur = this;
			EditStyle.setVisible(true);
		}
	},

	/** Renvoit le chemin absolu CSS de l'élément */
	cheminAbsolu: function(element) {
		var root = element;
		var path = new Array();
		var pathRetour = new Array();
		var somePaths = false;
		var i = 0;

		if(window.location.pathname.lastIndexOf('.') != -1)
			var pageActuelle = window.location.pathname.substring(window.location.pathname.lastIndexOf('/')+1, window.location.pathname.lastIndexOf('.'));
		else
			var pageActuelle = 'index';

		do {
			/* 	Ici se trouvent des modifs pour PunBB
				But : ne plus s'encombrer de <div id="brd-index" class="brd-page basic-page">
				(id spécifique aux pages et la double-class inutile partout)
			*/

			if(!Outils.empty(root.id) && root.id != 'brd-' + pageActuelle && root.id != 'pun' + pageActuelle) // PunBB
				path[i] = root.nodeName + '#' + root.id;
			else if(!Outils.empty(root.className)) {

				// Cas du class="style1 style2"
				if(/ /.test(root.className) && !/brd-page/i.test(root.className)) { // PunBB
					somePaths = true;
					path[i] = new Array();
					var paths = root.className.split(/ /g);
				
					// Création d'un tableau contenant les branches
					for(var j = 0; j < paths.length; j++)
						path[i][j] = root.nodeName + '.' + paths[j];
				} else
					path[i] = root.nodeName + '.' + (/brd-page/i.test(root.className) ? 'brd-page': root.className); // PunBB
			} else
				path[i] = root.nodeName;

			i++;
		} while((root = root.parentNode) && !/html/i.test(root.nodeName));

		path.reverse();
	
		// Si au moins une fourchette a été détectée, recherche de toutes les possibilités
		pathRetour['stringPaths'] = somePaths ? Outils.findAllPaths(path) : new Array(path.join(' '));

		// Tableaux des éléments du chemin CSS (1 fourchette = 1 array)
		pathRetour['arrayPath'] = path;

		// Méthode de copie du ou des noms de l'élément courant
		pathRetour['arrayPath'].copieLast = function() {
			var last = this[this.length-1];

			if(Outils.isArray(last)) {
				var retour = new Array();

				for(var p = 0; p < last.length; p++)
					retour[p] = last[p];
			} else
				retour = last;

			return retour;
		};

		return pathRetour;
	},

	/** Cas des class="style1 style2" : calcul de tous les paths possibles */
	findAllPaths: function(path) {
		var allPaths = new Array();
		allPaths[0] = '';

		// Parcours des éléments du path
		for(var i = 0; i < path.length; i++) {

			// Un seul className ou un id
			if(typeof path[i] != 'object') {
				for(var j = 0; j < allPaths.length; j++)
					allPaths[j] += ' ' + path[i];

			} else { // Plusieurs classNames
				var tailleFixe = allPaths.length;
			
				for(var j = 0; j < tailleFixe; j++) { // Parcours de tous les paths déjà créés
					for(var k = 1; k < path[i].length; k++) // Parcours des différents classNames trouvés
						allPaths.push(allPaths[j] + ' ' + path[i][k]); // Ajout de tous les nouveaux parcours au parcours initial courant

					allPaths[j] += ' ' + path[i][0];
				}
			}
		}

		// Suppression des espaces initiaux		
		for(var j = 0; j < allPaths.length; j++)
			allPaths[j] = allPaths[j].substring(1);

		return allPaths;
	},

	/** Coordonnées de la souris */
	cooMouse: function(e) {
		return [
			parseInt(e ? e.clientX : window.event.clientX) + parseInt(document.body.scrollLeft || document.documentElement.scrollLeft),
			parseInt(e ? e.clientY : window.event.clientY) + parseInt(document.body.scrollTop || document.documentElement.scrollTop)
		];
	},

	/** Convertion d'un nom de propriété de CSS à javascript */
	propCSS2JS: function(css) {
		var reg = new RegExp('(\-[a-z4]{1})', 'g'), js;

		while(js = reg.exec(css))
			css = css.replace(js[1], js[1].charAt(1).toUpperCase());

		return css;
	},

	/** Changement de flotteur */
	changeFlotteur: function() {
		var root = this.menu.declencheur;
		Outils.coordonnees = [root.coordonnees[0], root.coordonnees[1]];

		for(var i = 1; i < this.value; i++)
			root = root.parentNode;

		EditStyle.removeMenu.apply(this.menu);
		root.onmousedown();
	},
	
	/** Accès au noeud précédent (historique) */
	history: function(direction) {
		EditStyle.removeMenu.apply(this.menu);
		Outils.coordonnees = [this.menu.declencheur.coordonnees[0], this.menu.declencheur.coordonnees[1]];

		Outils.historiqueChange = true;

		if(direction == -1)
			Outils.historique[--Outils.historiquePointer].onmousedown();
		else
			Outils.historique[++Outils.historiquePointer].onmousedown();
	},

	/** Généralise la régle à tous les éléments du même type et du même niveau que le flotteur */
	generalisation: function() {
		var declencheur = this.spkNodeBrowser.menu.declencheur;
		var maj = false;
		var libelle = '';

		if(this.checked)
			this.spkNodeBrowser.generalized[this.value] = new Array();

		// Parcours des chemins et suppression de la class ou l'id
		for(var p = 0; p < declencheur.paths['stringPaths'].length; p++) {

			// Séparation des éléments du selecteur
			var elements = declencheur.paths['stringPaths'][p].split(/ /g);
			declencheur.paths['stringPaths'][p] = '';

			// Parcours des éléments
			for(var e = 0; e < elements.length; e++) {
				declencheur.paths['stringPaths'][p] += ' ';

				// C'est l'élément qu'on souhaite généraliser/pointer
				if(e == elements.length - this.value) {

					// Généralisation
					if(this.checked) {

						// Sauvegarde de l'élément complet
						this.spkNodeBrowser.generalized[this.value][p] = elements[e];

						if(!maj) {
							// Abstraction de l'identifiant ou la classe
							maj = /^([A-Z0-9-]+)[.#]?[A-Z0-9-]*:?([A-Z-]*)$/i.exec(elements[e]);
							maj = maj[1] + (!Outils.empty(maj[2]) ? ':' + maj[2] : '');
						}

					// Pointage
					} else {
						maj = this.spkNodeBrowser.generalized[this.value][p];
						
						if(!(new RegExp(maj, 'i')).exec(libelle))
							libelle += '/' + maj;
					}

					declencheur.paths['stringPaths'][p] += maj;
				} else
					declencheur.paths['stringPaths'][p] += elements[e];
			}

			declencheur.paths['stringPaths'][p] = declencheur.paths['stringPaths'][p].substring(1);
		}

		if(!this.checked) {
			maj = libelle.substring(1);
			delete this.spkNodeBrowser.generalized[this.value];
		}

		// L'élément est-il un block ou un inline		
		var element = this.spkNodeBrowser.menu.declencheur;
		for(i = 1; i < this.value; element = element.parentNode, i++);
		var display = window.getComputedStyle ? window.getComputedStyle(element, null).display : element.currentStyle.display;
		maj += ' (' + (display == 'inline' ? 'I' : 'B') + ')';

		// Mise à jour du libellé courant du navigateur de noeuds
		this.spkNodeBrowser.childNodes[this.spkNodeBrowser.childNodes.length - this.value].innerHTML = maj;
		this.previousSibling.innerHTML = Affichage.formatOption(maj);
	},

	/** Transforme une couleur rgb en hexadécimal */
	rgb2hexa: function(rgb) {

		/** Convertir un décimal en hexadécimal
		  * http://www.jonasjohn.de/snippets/javascript/dec2hex.htm
		  */
		Outils.rgb2hexa.dec2hex = function(n) {
			n = parseInt(n);
		
			var c = 'ABCDEF';
			var b = n / 16;
			var r = n % 16;
		
			b = b-(r/16); 
			b = (b >= 0 && b <= 9) ? b : c.charAt(b-10);
		
			return (r >= 0 && r <= 9) ? b + '' + r : b + '' + c.charAt(r-10);
		};

		// Extraction des codes décimaux
		rgb = /rgb\({1}([0-9]{1,3}), ?([0-9]{1,3}), ?([0-9]{1,3})\)/i.exec(rgb);
		var couleurHexa = '#';

		// Conversion
		for(var i = 1; i < rgb.length; i++)
			couleurHexa += Outils.rgb2hexa.dec2hex(rgb[i] > 255 ? 255 : rgb[i]);

		return couleurHexa;
	},

	/** Correspondance des valeurs entre navigateurs */
	setGeneric: function(valeur) {
		var correspondances = {
			// Couleurs anglaises
			black: '#000000', maroon: '#800000', green: '#008000', olive: '#808000', navy: '#000080', purple: '#800080',
			teal: '#008080', gray: '#808080', silver: '#C0C0C0', red: '#FF0000', lime: '#00FF00', yellow: '#FFFF00',
			blue: '#0000FF', fuchsia: '#FF00FF', aqua: '#OOFFFF', white: '#FFFFFF',

			// Tailles du navigateur (IE met medium lorsque rien n'est défini)
			medium: '0px',

			// Alignement
			start: 'left',
			end: 'right',

			// Graisses
			400: 'normal', 700: 'bold'
		};

		// Bas de casse
		(typeof valeur != 'number') ? valeur = valeur.toLowerCase() : null;

		// Normalisation de la notation
		if(Outils.isset(correspondances[valeur]))
			return correspondances[(typeof valeur == 'number') ? valeur : valeur.toLowerCase()];
	
		// C'est une couleur
		if(/^(#|rgba?\()/i.test(valeur)) {
			valeur = valeur.toUpperCase();

			// C'est une couleur RGB : passage en hexa
			if(/rgba?/i.test(valeur)) {
				if(/rgba/i.test(valeur)) { // Safari
					if(/, ?0+\)$/.test(valeur))
						return 'transparent';

					valeur = valeur.replace(/, ?[0-9]+\)$/i, ')');
					valeur = valeur.replace(/rgba/i, 'rgb');
				}

				return Outils.rgb2hexa(valeur);
			}

			// Vérification que le code hexa est correct, sinon correction
			else {
				if(valeur.substr(0,1) != '#')
					valeur = '#' + valeur;

				if(valeur.length > 7)
					valeur = valeur.substr(0, 7);
	
				else if(valeur.length < 7) {
					if(valeur.length == 4)
						valeur = '#' + valeur.substr(1,1) + valeur.substr(1,1) + valeur.substr(2,1) + valeur.substr(2,1) + valeur.substr(3,1) + valeur.substr(3,1);
					else
						while(valeur.length < 7)
							valeur += 0;
				}
			}
		}

		// Divers
		(valeur == '?') ? valeur = '' : null;
		return (valeur == '0') ? '0px' : valeur;
	},

	/** Choisir une couleur */
	colorPicker: function() {
		var picker = document.createElement('div');

		// Propriétés
		picker.id = 'spkColorPicker';
		picker.className = picker.id;
		picker.champ = this;
		picker.style.left = this.declencheur.coordonnees[0] + 'px';
		picker.style.top = this.declencheur.coordonnees[1] + 'px';
		
		// Object XMLHttpRequest
		var getColorPicker = window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : null);

		// Préparation
		getColorPicker.open('GET', Parametres.root + 'colorPicker.php', true);

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

			// Données reçues
			if(getColorPicker.readyState == 4) {
				// Disparition du message d'attente
				document.getElementById('spkPatientez').style.display = 'none';

				// Ajout du colorPicker
				document.body.appendChild(picker);
				Outils.repositionnement.apply(picker);
				picker.style.top = parseInt(picker.style.top) - 10 + 'px';
				picker.innerHTML = getColorPicker.responseText;

				// Initialisation
				new Refresh.Web.ColorPicker('spk', { startHex: (picker.champ.value == 'transparent') ? 'FFFFFF' : picker.champ.value.substring(1), startMode: 'h' });
				document.getElementById('spk_Hex').focus();
				document.getElementById('spk_Hex').select();
			}
		};
		
		// Envoi
		getColorPicker.send(null);
	},

	/** Suppression du colorPicker */
	removeColorPicker: function() {
		var elements = document.getElementsByClassName('spkColorPicker');
		for(var i = elements.length; i > 0; document.body.removeChild(elements[--i]));
	},
	
	/** Changement de libellé */
	changeLibelle: function() {
		var champs = document.getElementById(this.name).childNodes;

		for(var i = 0; i < champs.length; i++)
			if(/(input|select)/i.test(champs[i].nodeName) && champs[i].className != 'spkColorPreview' && champs[i].className != 'spkUnite') {

				// Mise à jour du nom du champ
				Outils.changeCard(champs[i], this.value);
			
				// Mise à jour de la valeur
				EditStyle.loadInit.apply(champs[i]);
			}
	},
	
	/** Mise à jour du nom d'un champ (chgmt de cardinalité) */
	changeCard: function(champ, card) {
		var reg = new RegExp('-(top|right|bottom|left|4c)', 'i');

		champ.name = champ.name.replace(reg, '-' + card);
		champ.jsName = Outils.propCSS2JS(champ.name);
	},

	/** Déplacement du menu */
	deplacer: function(e) {
		var coo = Outils.cooMouse(e);
		var menu = document.getElementById('spinkbb');
		var flotteur = menu.declencheur;
		
		flotteur.coordonnees[0] = coo[0] - 5;
		flotteur.coordonnees[1] = coo[1] - 5;

		menu.style.left = flotteur.coordonnees[0] + 'px';
		menu.style.top = flotteur.coordonnees[1] + 'px';
	},
	
	/** Repositionnement du menu */
	repositionnement: function() {
		var dimMenu = [parseInt(this.offsetWidth), parseInt(this.offsetHeight)];
		var position = [parseInt(this.style.left), parseInt(this.style.top)];
		var heightPanel = parseInt(Affichage.topPanel.offsetHeight);

		var dimFenetre = [ // Dimensions de la fenêtre
			window.pageXOffset ? parseInt(window.pageXOffset) + parseInt(window.innerWidth) : parseInt(document.documentElement.scrollLeft) + parseInt(document.documentElement.clientWidth),
			window.pageYOffset ? parseInt(window.pageYOffset) + parseInt(window.innerHeight) : parseInt(document.documentElement.scrollTop) + parseInt(document.documentElement.clientHeight),
		];

		if(position[0] > dimMenu[0] && dimFenetre[0] < dimMenu[0] + position[0])
			this.style.left = position[0] - dimMenu[0] + 'px';

		if(position[1] > dimMenu[1] + heightPanel && dimFenetre[1] < dimMenu[1] + heightPanel + position[1])
			this.style.top = position[1] - dimMenu[1] + 'px';

		return (position[0] != parseInt(this.style.left) || position[1] != parseInt(this.style.top));
	},
	
	/** Sauvegarde les valeurs des propriétés du lien lorsqu'il est survolé */
	saveHover: function(proprietes) {
		var styles = window.getComputedStyle ? window.getComputedStyle(this, null) : this.currentStyle;
		
		// Parcours des propriétés dont la valeur est à enregistrer
		for(var element in proprietes)
			if(!Outils.isFunction(proprietes[element])) {
				if(Outils.isArray(proprietes[element]))
					// Si c'est un tableau de propriétés on part les crawler
					Outils.saveHover.call(this, proprietes[element]);
				else {
					var card = ['Top', 'Right', 'Bottom', 'Left'];
					var jsName = Outils.propCSS2JS(proprietes[element]);

					// On récupére les 4 valeurs si c'est un 4c
					if(/4c/i.test(jsName)) {
						for(var i = 0; i < card.length; i++)
							this.stylesHover[jsName.replace('4c', card[i])] = styles[jsName.replace('4c', card[i])];
							
					// Sinon récupération directe de la valeur
					} else
						this.stylesHover[jsName] = styles[jsName];
				}
			}
	},


	/** Méthodes diverses */

	patientez: function(id) {
		// Création
		if(!Outils.isset(document.getElementById(id))) {
			var patientez = document.createElement('div');
			var libellePatientez = document.createTextNode(Langues.get('Patientez'));

			patientez.id = id;
			patientez.appendChild(libellePatientez);
			document.body.appendChild(patientez);
		}
	
		// Position fixed pour IE
		if(navigator.userAgent.indexOf('MSIE 6') != -1) {
			document.getElementById(id).style.position = 'absolute';

			window.onscroll = function() {
				document.getElementById(id).style.top = parseInt(document.documentElement.scrollTop) + 'px';
			}
		}

		// Apparition
		document.getElementById(id).style.display = 'block';
	},
	
	sortTab: function(tab) {
		for(var i = 1; i < tab.length; i++) {
			i = (i == 0) ? i++ : i;

			if(tab[i] < tab[i-1]) {
				while(i > 0 && tab[i] < tab[i-1]) {
					var inter = tab[i];
					tab[i] = tab[i-1];
					tab[i-1] = inter;
					i--;
				}
			}
		}
		
		return tab;
	},

	empty: function(variable) {
		return (variable == '' || variable == 0 || variable == null || (variable.length && variable.length == 0));
	},

	isset: function(variable) {
		return (typeof variable != 'undefined' && variable != null);
	}, // Ne marche pas pour event....

	isArray: function(variable) {
		return (typeof variable == 'object');
	},

	isFunction: function(variable) {
		return (typeof variable == 'function');
	},
	
	parseFloatFr: function(valeur) {
		return parseFloat(valeur.match(',') ? valeur.replace(',', '.') : valeur);
	}
};

