/*
 * Sistemare il problema del posizionamento degli elementi iniziali:
 * calcolare il primo offset, e allineare i successivi elementi inseriti
 * tramite quello.
 * Sistemare i nomi degli effetti in modo che siano significativi
 * aggiungere (e documentare) un po' di parametri di inizializzazione
 */

if(typeof dhiafora == 'undefined')
	var dhiafora = {};
dhiafora.fx = {};

dhiafora.fx.SlideShow = function(el, opt) {
	//- Constructor -\\
	function init() {
		container = $(el);
		if(!opt) opt = {};
		//option:
		//duration: durata dell'effetto (in ms), default: 3.5 secondi
		//interval: intervallo tra due effetti consecutiri (in ms),
		//          default: il triplo di duration
		//doSlide: se true esegue uno spostamento della foto default: false
		//concurrent: se true esegue lo spostamento contemporaneamente al fade
		//          default: false
		fxDuration = opt.duration || 3500;
		fxInterval = opt.interval || 3 * fxDuration;
		doSlide = opt.slide || false;
		concurrent = opt.concurrent || false;
		$each(container.getElementsByTagName('img'), function (img, index) {
			if(img.src) {
				var box = $(img).getParent();
	 			images.push(img);
				positionImageBox($(box));
				img.setOpacity(1);
				var cmt = img.getNext();
				if(cmt)
					cmt.setOpacity(.4);
				//console.debug('%o', img.getNext());
			}
		}, this);
	}
	
	//- Public Methods -\\
	this.addElement = function(o) {
	 	if(!o.img) throw new Exception('Elemento non valido ' + o);
	 	var img = createBoxElement(o.img, o.msg);
		img.addEvent('load', imageLoaded.bindWithEvent(this, img));
	}
	
	this.start = function() {
		running = true;
		timer = stepForward.periodical(fxInterval, this);
	}

	this.next = function() {
		stepForward();
	}

	this.previous = function() {
		stepBack();
	}

	this.stop = function() {
		if(!running) return;
		running = false;
		$clear(timer);
	}
	
	//- Utility Methods -\\
	this.setEffectDuration = function(duration) {
		fxDuration = duration;
	}
	
	this.setEffectInterval = function(interval) {
		fxInterval = interval;
	}
	
	this.setSlide = function(slide) {
		doSlide = slide;
	}
	
	//- Private Section -\\
	
	/*
	 * Callback dell'evento di caricamento di un' immagine
	 */
	function imageLoaded(e, img) {
	 	images.push(img);
		var box = img.getParent();
		container.appendChild(box);
		img.setOpacity(0);
		positionImageBox(box);
		//console.debug('Immagine caricata %s, totale=%i', img.src, images.length);
		//img.setOpacity(.1);
	}
	
	function positionImageBox(box) {
		var size = box.getSize().size;
		var position = box.getPosition();
		var t = -(parseInt(position.y / size.y) * size.y) + 'px';
		var l = -(parseInt(position.x / size.x) * size.x) + 'px';
		box.setStyles({left:l, top:t});
		
		var screen = box.getFirst().getNext();
		if(screen) {
			size = box.getSize().size;
			position = screen.getPosition();
			t = -(parseInt(position.y / size.y) * size.y) + 'px';
			l = -(parseInt(position.x / size.x) * size.x) + 'px';
			screen.setStyles({
				background: '#000',
				opacity: 0
			});
		}
		/* *
		console.debug('Dimensioni immagine: w=%i, h=%i', size.x, size.y);
		console.debug('Posizione immagine: x=%i, y=%i', position.x, position.y);
		console.debug('Nuova posizione: x=%i, y=%i', l, t);
		/* */
	}
	
	/*
	 * Crea un elemento img per le immagini caricate via javascript
	 * tramite il metodo addImage
	 *
	 * @param url l'url dell'immagine
	 * @return un riferimento all'elemento creato
	 */
	function createBoxElement(url, msg) {
		//console.debug('Crea elemento img src=%s', url);
		var box = new Element('div', {
			'class': 'imageBox'
		});
		var img = new Element('img', {
			'src': url
		});
		box.appendChild(img);
		var comment = new Element('div', {
			'class': 'commento'
		});
		comment.appendChild(document.createTextNode(msg || ''));
		box.appendChild(comment);
		return img;
	}
	
	function stepForward() {
		if(images.length < 2) return;
		var curImg = $(images[imageIndex]);//ie fix
		imageIndex = ++imageIndex % images.length;
		var nextImg = images[imageIndex];
		doTransition(curImg, nextImg);
	}
	
	function stepBack() {
		if(images.length < 2) return;
		var curImg = $(images[imageIndex]);//ie fix
		imageIndex = ++imageIndex % images.length;
		var nextImg = images[imageIndex];
		doTransition(curImg, nextImg);
	}
	
	function doTransition(curImg, nextImg) {
		//console.debug("Visualizza %s immagine %i di %i", nextImg.src, imageIndex, images.length);
		var imgFadeOut = new Fx.Style(curImg, 'opacity',
			{duration: fxDuration, transition: Fx.Transitions.sineInOut}
		);
		var imgFadeIn = new Fx.Style(nextImg, 'opacity',
			{duration: fxDuration, transition: Fx.Transitions.sineInOut}
		);
		
		var cmtFadeOut = new Fx.Style(curImg.getNext(), 'opacity',
			{duration: fxDuration, transition: Fx.Transitions.sineInOut}
		);
		
		//Dove li mettiamo questi, per rendere il tutto parametrico?
		var cmtInFrom = -300;
		var cmtInTo = -380;
		var cmtSlideIn = new Fx.Style(nextImg.getNext(), 'top',
			{duration: fxDuration/2, transition: Fx.Transitions.sineInOut,
				onStart: function() {
					nextImg.getNext().setStyle('top', cmtInFrom);
					cmtSlideIn.element.setOpacity(.4);
				}
			}
		);
		
		if(doSlide) {//opzione slide + fade
			var imgMoveOut = new Fx.Styles(curImg,
				{duration: fxDuration, transition: Fx.Transitions.sineInOut}
			);
			var lNow = parseInt(curImg.getStyle('left'));
			var tNow = parseInt(curImg.getStyle('top'));
			var alpha = Math.random() * 2 * Math.PI;
			var len = $random(40, 100);
			var lOff = parseInt(len * Math.cos(alpha));
			var tOff = parseInt(len * Math.sin(alpha));
			//console.debug('movimento a:%i, l:%i, x:i%, y:%i', alpha, len, lOff, tOff);
			
			imgFadeOut.addEvent('onComplete', function() {
					curImg.setStyles({left:lNow, top:tNow});
				}
			);
			//esecuzione concorrente degli effetti
			if(concurrent) {
				imgMoveOut.start({'left': lNow + lOff, 'top': tNow + tOff});
				imgFadeOut.start(1,0);
				imgFadeIn.start(0,1);
			} else {
				//esecuzione sequenziale: prima si muove l'immagine, poi fade
				//il fade comincia all'50% dello spostamento
				(function() {
					imgFadeOut.start(1,0);
					imgFadeIn.start(0,1);
					cmtFadeOut.start(.4,0);
				}).delay(fxDuration * .5);
				
				//dopo che la nuova immagine è presente, compare anche il commento
				(function() {
					cmtSlideIn.start(cmtInFrom, cmtInTo);
				}).delay(fxDuration * 1.5);
				imgMoveOut.start({'left': lNow + lOff, 'top': tNow + tOff});
			}
		//se invece non si vuole lo slide, ma solo il fade
		} else {
			imgFadeOut.start(1,0);
			imgFadeIn.start(0,1);
		}
	}
	//tutte le immagini della galleria
	var images = $A();
	//elemento HTML che fa da contenitore (a cui appiccicare le nuove immagini
	var container;
	//falg che indica se funziona o no, 
	var running = false;
	//contatore per tenere traccia dell'immagine corrente
	var imageIndex = 0;
	//parametro timer restituito dall'esecuzione periodica degli effetti
	//serve per rilasciare la memoria una volta finito
	var timer = null;
	//durata (in ms) dell'effetto
	var fxDuration;
	//intervallo (in ms) tra un effetto e l'altro
	//deve essere fxInterval >= fxDuration
	//se no si fa casino
	var fxInterval;
	//abilita l'effetto di movimento
	var doSlide;
	//imposta se l'effetto di movimento deve essere assieme al fade, o prima
	var concurrent;
	//chiama il costruttore in ultimo!!!
	init();
}

dhiafora.fx.Direction = function() {
	/*
	 * x, y lunghezza sugli assi
	 * l = (int)Math.sqrt(x*x + y*y)
	 * a = Math.atan2(y, x)
	 * 
	 * a, l angolo (in radianti) e lunghezza
	 * x = (int)l * Math.cos(a)
	 * y = (int)l * Math.sin(a)
	 * 
	 * s: velocità
	 * t: tempo
	 * 
	 * s = l/t
	 * l = s*t
	 */
	var dir; //angolo compreso tra 0 e 2*Math.PI
	var lenght; //distanza in pixel
}

