/**
 * Dependencias:
 * 		Prototype 1.6
 * 		Script.aculo.us 1.8: modulo Effect
 * 
 * 
 * 
 *  BUGS
 * - No funciona sin Background
 */

var ProtoSlider = Class.create({
	
	options_layout: {
		delay: 5000,		// Tiempo que tarda cada diapositiva en pasar
		paginate: true,	// Indica si mostrará la paginación
		tranxDelay: 500,	// Tiempo que tarda el efecto
		position: 0,		// Diapositiva en la que empieza
		diapoClass: null,
		transition: 'move',
		restartEffect: 'fade', // [fade,move,continue] Indica como volver a la primera diapositiva al llegar al final. (continue no está implementado aún).
		autoPlay: true,		// Indica si se inicia reproduciendose
		classes:{
			slider: 'slider',	// Elemento que se mueve
			container: null,		// Elemento contenedor de las diapositivas
			pagination: 'pagination',
			paginationPage: 'page',
			background: 'background'	// Fondo
		},
		elements:[],
		titles:[]
	},
	
	playing : false, // Indica si se está reproduciendo
	diapos : [], // Array con las diapositivas
	container: null, // Container
	subCont : null, // Container que contiene las diapositivas. Es el que se mueve
	position: null, // Número de diapositiva que se vé. Empieza en 0.
	timeOut: null, // Guarda el objeto intervalo que ejecuta la animación periódica
	pagination: null, // Guarda el elemento de paginación
	
	/**
	 * Iniciliza una animación.
	 * @param {Object} container:	Elemento que contiene las diapositivas
	 * @param {Object} options:		Objeto de opciones. Se mergea con options_layout
	 */
	initialize: function(container,options){
		
		// Cargamos las opciones
		this.options = Object.clone(this.options_layout);
		if(options && options.classes) Object.extend(this.options.classes,options.classes); // Clases
		Object.extend(this.options,options);
		this.position = this.options.position;
		
		// Cargamos el container general
		this.container = $(container).setStyle({overflow: 'hidden',display:'block'}).addClassName(this.options.classes.container);
		
		// Localizamos las diapositivas
		if(this.options.diapoClass) this.diapos = this.container.select('.'+this.options.diapoClass);
		else this.diapos = this.container.immediateDescendants();
		// Localizamos el fondo (si hay)
		this.background = this.container.select('.'+this.options.classes.background)[0];
		
		// Añadimos las diapositivas pasadas por opciones
		/*
		this.options.elements.each(function(item){
			this.diapos[this.diapos.size()] = item;
		}.bind(this));
		*/
		// Creamos el container movible de las diapositivas
		this.subCont = new Element('div').makePositioned().setStyle({
			'width': this.container.getDimensions().width*this.diapos.size()+'px',
			'height': this.container.getDimensions().height+'px', // 
			'left': -this.container.getDimensions().width*this.options.position+'px'
		}).addClassName(this.options.classes.slider);
		
		// Insertamos las diapositivas en el container movible
		this.diapos.each(function(item){
			this.subCont.insert(new Element('div').insert(item).setStyle({
				'width': this.container.getDimensions().width+'px',
				'height': this.container.getDimensions().height+'px',
				'overflow': 'hidden',
				'display': 'block',
				'float': 'left'
			}));
		}.bind(this));
		this.container.insert(this.subCont);
				
		// Creamos la paginación
		if(this.options.paginate){
			this.pagination = new Element('div').addClassName(this.options.classes.pagination);
			for (i = 0; i < this.diapos.size(); i++) {
				var page = new Element('div')
					.addClassName(this.options.classes.paginationPage)
					.observe('click',function(e,item){
						this.moveTo(e.target.diapos);
					}.bind(this))
				page.diapos = i;
				if(typeof(this.options.titles[i])!='undefined') page.insert(this.options.titles[i]);
				else page.insert(i+1);
				this.pagination.insert(page);
			}
			
			this.stopButton = new Element('div')
				.addClassName(this.options.classes.paginationPage)
				.addClassName('stopButton')
				.insert('Stop')
				.observe('click',function(e){
					this.stop();
					this.playButton.show();
					e.target.hide();
				}.bind(this));
			
			this.playButton = new Element('div')
				.addClassName(this.options.classes.paginationPage)
				.addClassName('playButton')
				.insert('Play')
				.observe('click',function(e){
					this.play();
					this.stopButton.show();
					e.target.hide();
				}.bind(this));
			
			if(this.autoPlay) this.stopButton.hide();
			else this.playButton.hide();
			
			this.pagination.insert(this.stopButton).insert(this.playButton);
			this.container.insert(this.pagination)
			
			//.observe('mouseover',function(){this.pagination.setOpacity(1)}.bind(this))
			//.observe('mouseout',function(){this.pagination.setOpacity(0)}.bind(this));
			//this.pagination.setOpacity(0);
			this.pagination.descendants()[this.position].addClassName('active');
		}
		this.container
			//.observe('mouseover',function(){this.stop()}.bind(this))
			//.observe('mouseout',function(){this.play()}.bind(this))
		
		// Lo ponemos en la posición inicial
		if(this.options.autoPlay) this.play();
		
	},
	
	/**
	 * Mueve una diapositiva hacia delante
	 */
	moveFwd: function(){this.moveTo(this.position+1);},
	
	/**
	 * Mueve una diapositiva hacia atras
	 */
	moveBwd: function(){this.moveTo(this.position-1);},
	
	/**
	 * Mueve a una diapositiva específica
	 * @param {Object} position:	Número de diapositiva que mostrar
	 * @param {string} effect [move,fade]:	Efecto con el que se realizará latransición.
	 */
	moveTo: function(position,effect){
		clearTimeout(this.timeOut); // Anulamos la espera que haya ahora
		this.pagination.select('.page.active').each(function(item){item.removeClassName('active')}); // Quitamos la clase de selecccionado a la diapositiva actualmente seleccionada
		if (position >= this.diapos.size()) {position = 0; effect = this.options.restartEffect;} // Si se sale por arriba lo pone en 0
		if (position < 0) {position = this.position.size - 1; effect = this.options.restartEffect;} // Si se sale por abajo lo pone en la última
		// Realiza el movimiento según el efecto seleccionado
		switch(effect || this.options.transition){
			case 'move':
				new Effect.Move(this.subCont,{x:-this.container.getDimensions().width*position,	mode:'absolute', duration:1.5, afterFinish:this.transitionEnd.bind(this)});
				//console.log(this.background);
				//new Effect.Move(this.background,{x:-this.container.getDimensions().width*position/2, mode:'absolute', duration:1.5}); // Movemos el fondo
				break;
			case 'fade':
				this.subCont
				.fade({afterFinish:function(){this.subCont.setStyle({left: -this.container.getDimensions().width*position+'px'})}.bind(this)})
				.appear({from:0,	to:1,queue: 'end',afterFinish: this.transitionEnd.bind(this)});
				/*
				this.background // Movemos el fondo
				.fade({afterFinish:function(){this.subCont.setStyle({left: '0px'})}.bind(this)})
				.appear({from:0,	to:1,queue: 'end'});
				*/
				break;
		}
		this.position = position; // Actualiza la posición
	},
	
	/**
	 * Función que se ejecuta al terminar una transición.
	 * Establece un nuevo timeout.
	 */
	transitionEnd: function(){
		clearTimeout(this.timeOut);
		if(this.playing) this.timeOut = setTimeout(this.autoStep.bind(this),this.options.delay); // Establecemos la nueva espera
		this.pagination.descendants()[this.position].addClassName('active'); // Añadimos la clase "seleccionado" a la nueva diapositiva seleccionada
		// Si es la última diapositiva, y hay otras diapositivas, carga la siguiente
	},
	
	/**
	 * Detiene la animación
	 */
	stop: function(){
		clearTimeout(this.timeOut);
		this.playing=false;
	},
	
	/**
	 * Inicia la animación
	 */
	play: function(){
		this.playing = true;
		clearTimeout(this.timeOut);
		this.timeOut = setTimeout(this.autoStep.bind(this),this.options.delay);
	},
	
	/**
	 * Muestra la diapositiva siguiente. Si se pasa la última diapositiva, muestra la primera.
	 */
	autoStep: function(){
		this.moveFwd();
	}
});
