/*
 * Slideshow generator
 * Copyright (C) 2010 H. Nelson
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>
 */

// Base du Z Index CSS
var slideshowZIndexBase = 50

function slideshow(container) {
	// Numéro de l'élément actuellement affiché
	this.position = 0
	
	// Liste des éléments
	this.elements = []
	
	this.opacityIncrement = 0
	this.numberOfSteps = 15

	this.slideInterval = null
	this.fadeInterval = null
	
	var _ = this
	
	// Construit la pile, intialise les Z Index
	for (var i=0, el; el = container.children[i]; i++) {
		if (el.nodeType != Node.ELEMENT_NODE)
			continue
		
		this.elements.push(el)
		
		if (i == this.position) {
			el.opacity = 1
			el.style.opacity = 1
		}
		else {
			el.opacity = 0
			el.style.opacity = 0
		}
		
		// Indique pour chaque élément sa position dans la pile
		// l'élément ayant pour "order" 0 est celui "au dessus" des autres
		el.order = i
		
		// On calcule le Z Index en fonction de ce numéro dans la pile
		el.style.zIndex = slideshowZIndexBase + arguments.length - i - 1
	}
	
	// Joue/reprend la présentation aléatoire
	this.playRandomPresentation = function (slideInterval, animationInterval) {
		if (_.slideInterval)
			clearInterval(_.slideInterval);
		
		// Redéfini l'incrément d'opacité pour correspondre à la nouvelle durée
		_.opacityIncrement = _.numberOfSteps / animationInterval;
		
		_.slideInterval = setInterval(function () {
			var p;
			do {
				p = parseInt(Math.random() * _.elements.length);
			} while (p == _.position)
			_.slide(p, true)
			return 0
		}, slideInterval)
		
		return 0
	}
	
	// Joue/reprend la présentation
	this.playPresentation = function (slideInterval, animationInterval) {
		if (_.slideInterval)
			clearInterval(_.slideInterval)
		
		// Redéfini l'incrément d'opacité pour correspondre à la nouvelle durée
		_.opacityIncrement = _.numberOfSteps / animationInterval
		
		_.slideInterval = setInterval(function () {
			_.slide(_.position+1)
		}, slideInterval)
		
		return 0
	}
	
	// Met en pause la présentation
	this.pausePresentation = function () {
		clearInterval(_.slideInterval)
		_.slideInterval = null
		return 0
	}
	
	// Réorganise la pile et lance l'animation
	this.slide = function (pos) {
		if (pos == _.position || _.fadeInterval)
			return 1
		
		if (pos >= _.elements.length)
			pos = 0
		
		// L'élément désiré doit être visible avant le début de l'animation pour apparaître en dessous
		_.elements[pos].opacity = 1.
		_.elements[pos].style.opacity = 1.
	
		_.elements[pos].order = 0
		_.elements[_.position].order = 1
		
		// Lance l'animation
		_.fadeInterval = setInterval(function () {
			// Si l'élément courant a _disparu_
			if (_.fadeOut(_.elements[_.position])) {
				// Stop l'intervalle
				clearInterval(_.fadeInterval)
				_.fadeInterval = null
				for (var i=0, el; el = _.elements[i]; i++) {
					// Applique le Z Index relatif au nouvel ordre
					el.style.zIndex = slideshowZIndexBase - el.order + _.elements.length
				}
				// Change le numéro de l'élément actuellement affiché dans la liste
				_.position = pos
			}
			return 0
		}, 20)
		
		_.onslide(pos)
		
		if (_.elements[pos+1].src == "about:blank")
			_.elements[pos+1].src = _.elements[pos+1].alt
		
		return 0;
	};
	
	// Fait fondre en opacityé "el" et retourne "true" si il a disparu
	this.fadeOut = function (el) {
		el.opacity -= _.opacityIncrement
		if (el.opacity < 0.)
			el.opacity = 0.
		el.style.opacity = el.opacity
		return el.opacity == 0.
	}
	
	// Méthodes à écraser
	this.onslide = function(){}
	
	return this;
}

