

/**
 * Fichier obsolète : utiliser ev/gui/slidingBlocks.js à la place.
 */
(function() {
	var window = this,
			ev = window.ev,
			dom = ev && ev.dom,
			addClass = dom && dom.addClass,
			hasClass = dom && dom.hasClass,
			removeClass = dom && dom.removeClass;

	if (window.console && window.console.error) {
		window.console.error('FATAL : effects/slidingBlocks.js est DEPRECATED !! => Utiliser ev/gui/slidingBlocks.js à la place.');
	}

	/**
	 *
	 * @param _paneNode un élément DOM désignant le bloc conteneur des blocs coulissants.
	 * @param _delay durée en ms d'un coulissement.
	 * @param _upNode un élément DOM désignant le bloc permettant l'action de coulisser vers le haut.
	 * @param _downNode un élément DOM désignant le bloc permettant l'action de coulisser vers le bas.
	 * @param _leftNode un élément DOM désignant le bloc permettant l'action de coulisser vers la gauche.
	 * @param _rightNode un élément DOM désignant le bloc permettant l'action de coulisser vers la droite.
	 * @param _menuNode un élément DOM désignant le bloc parent d'un menu.
	 * @param _nbChildToDisplay est le nombre de blocs à afficher dans le bloc _paneNode.
	 * @param _sens vaut "horizontal" ou "vertical", paramètre optionel SAUF dans le cas où l'on veut afficher plus d'un élément à slider.
	 * @param _sens vaut "horizontal" ou "vertical", paramètre optionel SAUF dans le cas où l'on veut afficher plus d'un élément à slider.
	 * @param _defilement vaut "normal"(par défaut) ou "lent" ou "normalPause".
	 * @param _pause durée en ms d'une pause dans le cas d'un défilement.
	 *
	 * !!! Incompatible de faire défiler automatiquement quand il y a des flèches de contrôle
	 */
	function SlidingBlocksESV(_name,_paneNode,_delay,_upNode,_downNode,_leftNode,_rightNode,_menuNode,_nbChildHor,_nbChildVer,_sens,_defilement,_pause) {
		if (!_paneNode) { throw 'paneNode is undefined'; }
		if (typeof(_delay) !== 'number') { throw 'delay is not a number'; }

		/**
		 * Cette constante fixe le bloc conteneur des blocs coulissants.
		 */
		var paneNode = _paneNode;
		/**
		 * Gets the pane node, i.e; the sliding block.
		 */
		this.getPaneNode = function() {
			return paneNode;
		};
		/**
		 * Cette constante fixe la durée d'un coulissement en ms
		 */
		var delay = _delay;
		/**
		 * Cette constante fixe le nom de l'objet
		 */
		var name = _name;

		/**
		 * On définit la valeur de la margin-left initiale, finale, et courante
		 */
		var marginLeftStart = 0;
		var marginLeftEnd = 0;
		var marginLeft = marginLeftStart;

		/**
		 * On définit la valeur de la margin-top initiale, finale, courante
		 */
		var marginTopStart = 0;
		var marginTopEnd = 0;
		var marginTop = marginTopStart;

		/**
		 * On définit quel enfant est affiché par défaut
		 */
		var numeroBlockEnCours = 0;

		/**
		 * Ces constantes fixent les fleches permettant l'action de coulisser
		 */
		var upNode = _upNode,
				downNode = _downNode,
				leftNode = _leftNode,
				rightNode = _rightNode,
				menuNode = _menuNode;

		//par défaut on affiche 1 seul élément
		var nbChildHor,
				nbChildVer,
				sens,
				pause,
				defilement;

		if (typeof(_nbChildHor) !== 'number') {
			nbChildHor = 1;
		}
		else {
			nbChildHor = _nbChildHor;
		}

		if (typeof(_nbChildVer) !== 'number') {
			nbChildVer = 1;
		}
		else {
			nbChildVer = _nbChildVer;
		}

		//on définit le sens (permettant par la suite de définir ou non une largeur au marginBlok), par défaut le sens est horizontal
		if (_sens) {
			sens = _sens;
		}
		else {
			sens = 'horizontal';
		}

		//On calcule la durée de la pause, si aucune durée n'est précisée la pause passe en mode OFF.
		if (_pause) {
			pause = _pause + delay;
		}
		else {
			pause = 'OFF';
		}

		//On choisit un type de défilement
		if (_defilement) {
			defilement = _defilement;
		}
		else {
			defilement = 'normal';
		}


		/**
		 * This private constant defines the delay of the timeline internally used
		 * by the slider. CAUTION: modifying this constant can cause a strong
		 * resource consumption.
		 */
		var INTERVAL = 60;

		/**
		 * constante définissant l'action d'un coulissement horizontal vers la droite dans le cas d'un menu
		 */
		var HORIZONTALRIGHT = 0;
		/**
		 * constante définissant l'action d'un coulissement horizontal vers la gauche dans le cas d'un menu
		 */
		var HORIZONTALLEFT = 1;
		/**
		 * constante définissant l'action d'un coulissement vertical vers le haut dans le cas d'un menu
		 */
		var VERTICALUP = 2;
		/**
		 * constante définissant l'action d'un coulissement vertical vers le bas dans le cas d'un menu
		 */
		var VERTICALDOWN = 3;
		/**
		 * constante définissant une pause
		 */
		var PAUSE = 4;
		/**
		 * constante définissant une reprise
		 */
		var REPRISE = 5;

		var direction = HORIZONTALRIGHT;
		var directionEnCours;
		var numeroBlockToDisplay = 0;

		/**
		 * Ces constantes répupère la valeur des propriétés CSS height et width,
		 * qui DOIVENT être définies au préalable
		 */
		var paneNodeWidth = window.getStyleValue(paneNode, 'width');
		if (paneNodeWidth != 'none' && paneNodeWidth.match(/[0-9]+px/)) {
			paneNodeWidth = parseInt(paneNodeWidth.replace(/px/, ''), 10);
		}
		var paneNodeHeight = window.getStyleValue(paneNode, 'height');
		if (paneNodeHeight != 'none' && paneNodeHeight.match(/[0-9]+px/)) {
			paneNodeHeight = parseInt(paneNodeHeight.replace(/px/, ''), 10);
		}

		/**
		 * L'élément paneNode doit obligatoirement avoir pour enfant un (et un seul) élément de type div
		 * Cette obligation permet de définir une largeur plus importante sur ce bloc, permettant ainsi
		 * de placer les blocs côte à côte sur l'horizon dans le cas d'un défilement de droite à gauche.
		 * C'est sur cet élément de type DIV que nous allons faire varier le margin-top ou margin-left
		 */

		var marginBlock = window.firstChildByNodeType(paneNode, '1');

		/**
		 * Sur tout les enfants du marginBlock, on applique des styles CSS permettant le bon
		 * fonctionnement des coulissements. On récupère également le nombre d'enfants avec
		 * nbSlidingBlocks.
		 */
		var j = 0;
		var nbSlidingBlocks = 0;
		while (marginBlock.childNodes[j]) {
			if (marginBlock.childNodes[j].nodeType == 1 && marginBlock.childNodes[j].style.display != 'none') {
				nbSlidingBlocks++;
				marginBlock.childNodes[j].style.width = paneNodeWidth / nbChildHor + 'px';
				marginBlock.childNodes[j].style.height = paneNodeHeight / nbChildVer + 'px';
				marginBlock.childNodes[j].style.overflow = 'hidden';
				marginBlock.childNodes[j].style.cssFloat = marginBlock.childNodes[j].style.styleFloat = 'left';
			}
			j++;
		}
		nbSlidingBlocks = Math.ceil(nbSlidingBlocks / (nbChildHor * nbChildVer));
		//on cache la flèche affichée par défaut si l'on a qu'un seul élément dnas le slidingBlock
		if (rightNode && nbSlidingBlocks <= 1) {
			rightNode.style.visibility = 'hidden';
		}
		if (downNode && nbSlidingBlocks <= 1) {
			downNode.style.visibility = 'hidden';
		}

		//on définit la valeur du margin-top ou margin-left du dernier élément de la liste
		var marginTopMax = (nbSlidingBlocks * -paneNodeHeight) + paneNodeHeight;
		var marginLeftMax = (nbSlidingBlocks * -paneNodeWidth) + paneNodeWidth;

		var timeline = new window.Timeline(INTERVAL);

		/**
		 * Ces constantes définissent la valeur du margin-top ou margin-left
		 * qui sera ajoutée ou enlevée à chaque action de la timeline
		 */
		var incrementMarginLeft = paneNodeWidth / delay * INTERVAL;
		var incrementMarginTop = paneNodeHeight / delay * INTERVAL;

		//on modifie la largeur du marginBlock pour que les éléments puissent se caler
		if (sens == 'horizontal') {
			marginBlock.style.width = nbSlidingBlocks * paneNodeWidth + 'px';
		}

		function SlidingBlocksTimelineListener() {
			this.throwTimelineEvent = function(timelineEvent) {
				if (timelineEvent.getType() != window.TimelineEventType().STOP) {// START|RUNNING

					if (direction == VERTICALDOWN && marginTop - incrementMarginTop > marginTopEnd) {
						if (upNode) {
							upNode.style.visibility = 'visible';
						}
						marginTop = marginTop - incrementMarginTop;
						marginBlock.style.marginTop = marginTop + 'px';
					}

					else if (direction == VERTICALUP && marginTop + incrementMarginTop < marginTopEnd) {
						if (downNode) {
							downNode.style.visibility = 'visible';
						}
						marginTop = marginTop + incrementMarginTop;
						marginBlock.style.marginTop = marginTop + 'px';
					}
					else if (direction == HORIZONTALLEFT && marginLeft - incrementMarginLeft > marginLeftEnd) {
						if (leftNode) {
							leftNode.style.visibility = 'visible';
						}
						marginLeft = marginLeft - incrementMarginLeft;
						marginBlock.style.marginLeft = marginLeft + 'px';
					}

					else if (direction == HORIZONTALRIGHT && marginLeft + incrementMarginLeft < marginLeftEnd) {
						if (rightNode) {
							rightNode.style.visibility = 'visible';
						}
						marginLeft = marginLeft + incrementMarginLeft;
						marginBlock.style.marginLeft = marginLeft + 'px';
					}

					else {
						timeline.stop();
					}

					//on met à jour le numéro du bloc en cours
					if (sens == 'vertical' && marginTop <= (-paneNodeHeight * numeroBlockEnCours) - paneNodeHeight / 2) {
						numeroBlockEnCours = numeroBlockEnCours + 1;
					}
					if (sens == 'vertical' && marginTop > (-paneNodeHeight * numeroBlockEnCours) + paneNodeHeight / 2) {
						numeroBlockEnCours = numeroBlockEnCours + 1;
					}
					if (sens == 'horizontal' && marginLeft <= (-paneNodeWidth * numeroBlockEnCours) - paneNodeWidth / 2) {
						numeroBlockEnCours = numeroBlockEnCours + 1;
					}
					if (sens == 'horizontal' && marginLeft > (-paneNodeWidth * numeroBlockEnCours) + paneNodeWidth / 2) {
						numeroBlockEnCours = numeroBlockEnCours - 1;
					}

					if (menuNode) {
						//on gère les classes sur le menu
						var ArrayLiMenu = [],
								k = 0;
						while (menuNode.childNodes[k]) {
							if (menuNode.childNodes[k].nodeName != '#text') {
								if (!hasClass(menuNode.childNodes[k], 'neverSelectedSB')) {
									removeClass(menuNode.childNodes[k], 'selectedSB');
									ArrayLiMenu.push(menuNode.childNodes[k]);
								}
							}
							k++;
						}
						addClass(ArrayLiMenu[numeroBlockEnCours], 'selectedSB');
					}

				}
				else {// STOP
					if (direction == VERTICALUP) {
						marginBlock.style.marginTop = marginTopEnd + 'px';
						marginTopStart = marginTopEnd;
						marginTop = marginTopStart;
						//au premier element on cache la fleche du haut si elle existe
						if (upNode) {
							if (marginTopStart >= 0) {
								upNode.style.visibility = 'hidden';
							}
						}
					}
					else if (direction == VERTICALDOWN) {
						marginBlock.style.marginTop = marginTopEnd + 'px';
						marginTopStart = marginTopEnd;
						marginTop = marginTopStart;
						//au dernier element on cache la fleche du bas si elle existe
						if (downNode) {
							if (marginTopStart <= -nbSlidingBlocks * paneNodeHeight + paneNodeHeight) {
								downNode.style.visibility = 'hidden';
							}
						}
					}
					else if (direction == HORIZONTALLEFT) {
						marginBlock.style.marginLeft = marginLeftEnd + 'px';
						marginLeftStart = marginLeftEnd;
						marginLeft = marginLeftStart;
						//au dernier element on cache la fleche de droite si elle existe
						if (leftNode) {
							if (marginLeftStart <= -nbSlidingBlocks * paneNodeWidth + paneNodeWidth) {
								rightNode.style.visibility = 'hidden';
							}
						}
					}
					else if (direction == HORIZONTALRIGHT) {
						marginBlock.style.marginLeft = marginLeftEnd + 'px';
						marginLeftStart = marginLeftEnd;
						marginLeft = marginLeftStart;
						//au premier element on cache la fleche de gauche si elle existe
						if (leftNode) {
							if (marginLeftStart >= 0) {
								leftNode.style.visibility = 'hidden';
							}
						}
					}
					directionEnCours = -1;

					var nextBlock,
							prevBlock,
							nextActionJS,
							prevActionJS;

					//dans tous les cas on change la valeur de l'action de l'événement JS des fleches (si elles existent)
					if (sens == 'horizontal' && rightNode) {
						nextBlock = (numeroBlockToDisplay * 1) + 1;
						prevBlock = nextBlock - 2;
						nextActionJS = name + '.horizontal(' + nextBlock + ');';
						prevActionJS = name + '.horizontal(' + prevBlock + ');';
						if (nextBlock < nbSlidingBlocks + 1) {
							window.modifyJavascriptInAttribute(rightNode, 'onclick', nextActionJS);
						}
						if (prevBlock > 0) {
							window.modifyJavascriptInAttribute(leftNode, 'onclick', prevActionJS);
						}
					}
					if (sens == 'vertical' && downNode) {
						nextBlock = (numeroBlockToDisplay * 1) + 1;
						prevBlock = nextBlock - 2;
						nextActionJS = name + '.vertical(' + nextBlock + ');';
						prevActionJS = name + '.vertical(' + prevBlock + ');';
						if (nextBlock < nbSlidingBlocks + 1) {
							window.modifyJavascriptInAttribute(downNode, 'onclick', nextActionJS);
						}
						if (prevBlock > 0) {
							window.modifyJavascriptInAttribute(upNode, 'onclick', prevActionJS);
						}
					}
				}
			};
		}
		SlidingBlocksTimelineListener.prototype = new window.TimelineListener();
		timeline.addTimelineListener(new window.SlidingBlocksTimelineListener());

		/**
		 * Cette méthode fait défiler les éléments horizontalement pour afficher l'élément passer en paramètre.
		 **/
		this.horizontal = function(numeroNode) {
			numeroBlockToDisplay = numeroNode;

			//pour un défilement automatique de type lent
			if (defilement == 'lent') {
				//on fait défiler doucement jusqu'a la fin
				incrementMarginLeft = paneNodeWidth / (delay + pause) * INTERVAL;
			}

			if (!timeline.isRunning()) {
				//marginLeft margin actuel
				//marginLeftEnd margin final
				//marginLeftMax margin du dernier Element
				marginLeftEnd = (-numeroNode * paneNodeWidth) + paneNodeWidth;

				//on controle que le bloc a afficher est différent de l'actuel, et qu'il est inférieur au dernier disponible
				if (marginLeftEnd != marginLeft && marginLeftEnd >= marginLeftMax) {
					//si le bloc a afficher est en dessous de l'actuel, on diminue le margin
					if (marginLeft > marginLeftEnd) {
						direction = HORIZONTALLEFT;
						if (directionEnCours == HORIZONTALRIGHT) {
							marginLeftStart = marginLeftStart + paneNodeWidth;
						}
						directionEnCours = HORIZONTALLEFT;
						if (!timeline.isRunning()) {
							timeline.start();
						}
					}
					//si le block a afficher est au dessus de l'actuel, on augmente le margin
					if (marginLeft < marginLeftEnd) {
						direction = HORIZONTALRIGHT;
						if (directionEnCours == HORIZONTALLEFT) {
							marginLeftStart = marginLeftStart - paneNodeWidth;
						}
						directionEnCours = HORIZONTALRIGHT;
						if (!timeline.isRunning()) {
							timeline.start();
						}
					}
				}
			}
			//on ajoute un comportement en cas de changement d'element a affiché alors que la timeline est en cours
			else {
				marginLeftEnd = (-numeroNode * paneNodeWidth) + paneNodeWidth;
				if (marginLeft < marginLeftEnd) {
					direction = HORIZONTALRIGHT;
					if (directionEnCours == HORIZONTALLEFT) {
						marginLeftStart = marginLeftStart + paneNodeWidth;
					}
					directionEnCours = HORIZONTALRIGHT;
				}
				//si le block a afficher est au dessus de l'actuel, on augmente le margin-top
				if (marginLeft > marginLeftEnd) {
					direction = HORIZONTALLEFT;
					if (directionEnCours == HORIZONTALRIGHT) {
						marginLeftStart = marginLeftStart - paneNodeWidth;
					}
					directionEnCours = HORIZONTALLEFT;
				}
			}
		};

		/**
		 * Cette méthode fait défiler les éléments verticalement pour afficher l'élément passer en paramètre.
		 */
		this.vertical = function(numeroNode) {
			marginBlock.style.height = -marginTopEnd + 'px';
			numeroBlockToDisplay = numeroNode;

			//pour un défilement automatique de type lent
			if (defilement == 'lent') {
				//on fait défiler doucement jusqu'a la fin
				incrementMarginTop = paneNodeHeight / (delay + pause) * INTERVAL;
			}

			if (!timeline.isRunning()) {
				//marginTop margin actuel
				//marginTopEnd margin final
				//marginTopMax margin du dernier Element
				marginTopEnd = (-numeroNode * paneNodeHeight) + paneNodeHeight;

				//on controle que le bloc a afficher est différent de l'actuel, et qu'il est inférieur au dernier disponible
				if (marginTopEnd != marginTop && marginTopEnd >= marginTopMax) {
					//si le block a afficher est en dessous de l'actuel, on diminue le margin-top
					if (marginTop > marginTopEnd) {
						direction = VERTICALDOWN;
						if (directionEnCours == VERTICALUP) {
							marginTopStart = marginTopStart + paneNodeHeight;
						}
						directionEnCours = VERTICALDOWN;
						if (!timeline.isRunning()) {
							timeline.start();
						}
					}
					//si le block a afficher est au dessus de l'actuel, on augmente le margin-top
					if (marginTop < marginTopEnd) {
						direction = VERTICALUP;
						if (directionEnCours == VERTICALDOWN) {
							marginTopStart = marginTopStart - paneNodeHeight;
						}
						directionEnCours = VERTICALUP;
						if (!timeline.isRunning()) {
							timeline.start();
						}
					}
				}
			}
			//on ajoute un comportement en cas de changement d'element a affiché alors que la timeline est en cours
			else {
				marginTopEnd = (-numeroNode * paneNodeHeight) + paneNodeHeight;
				if (marginTop > marginTopEnd) {
					direction = VERTICALDOWN;
					if (directionEnCours == VERTICALUP) {
						marginTopStart = marginTopStart + paneNodeHeight;
					}
					directionEnCours = VERTICALDOWN;
				}
				//si le block a afficher est au dessus de l'actuel, on augmente le margin-top
				if (marginTop < marginTopEnd) {
					direction = VERTICALUP;
					if (directionEnCours == VERTICALDOWN) {
						marginTopStart = marginTopStart - paneNodeHeight;
					}
					directionEnCours = VERTICALUP;
				}
			}
		};

		this.pause = function() {
			direction = PAUSE;
			timeline.stop();
		};

		this.reprise = function() {
			direction = REPRISE;
			if (sens === 'vertical') {
				this.vertical(nbSlidingBlocks);
			}
			else {
				this.horizontal(nbSlidingBlocks);
			}
		};

		//on active ou pas le défilement automatique
		if (pause !== 'OFF') {
			if (sens === 'vertical') {
				this.vertical(nbSlidingBlocks);
			}
			else {
				this.horizontal(nbSlidingBlocks);
			}
		}
	}

	// raccourci pour dispo à l'extérieur
	window.SlidingBlocksESV = SlidingBlocksESV;
}());

