/**
 * Dependencias:
 * 		Prototype 1.6
 * 		Script.aculo.us 1.8: modulo Effect
 */

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'
		},
		elements:[]
	},
	
	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'}).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();
		
		// 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;
				this.pagination.insert(page);
			}
			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
	 */
	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)});
				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)});
				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();
	}
});