/*
Carrusel de imágenes con callbacks en los eventos importantes.
Utiliza un buffer oculto que va cargando la imagen siguiente en cuanto empieza a aparecer la anterior.

Uso:
	$('selector').carrusel(opciones);

	El nodo devuelto por el selector debe tener una o ninguna imagen. Si tiene una, se usa para el carrusel.
	Si no, se añade una con la primera imagen antes de empezar.

Opciones:
	id: Identificador del carrusel. Debe ser único.
	imagenes: Array de imágenes a mostrar.
	retraso: Tiempo de espera entre imágenes.
	velocidad: Velocidad de los fundidos.
	onFadeOut: Función llamada antes de empezar el fade out. La imagen actual sigue visible.
		id: Identificador del carrusel.
		actual: Foto que está desapareciendo.
	onAfterFadeOut: Función llamada al terminar el fade out. La imagen ya no es visible.
		id: identificador del carrusel.
		actual: Foto que ha desaparecido.
	onFadeIn: Función llamada antes de empezar el fade in. Las dos imágenes están ocultas.
		id: Identificador del carrusel.
		actual: Foto que empieza a aparecer.
	onAfterFadeIn: Función llamada cuando la nueva imagen es completamente visible.
		id: Identificador del carrusel.
		actual: Foto que se ha terminado de mostrar.
	
Ejemplo:
	HTML:
		<div id="imagen">
			<img src="i/imagen1.jpg" />
		</div>
		<div id="progreso">
			<ul>
				<li class="activo">1</li>
				<li>2</li>
				<li>3</li>
			</ul>
		</div>

	Script:
		$('#imagen').carrusel({
			imagenes: [ 'i/imagen1.jpg', 'i/imagen2.jpg', 'i/imagen3.jpg' ],
			retraso: 10000, // 10 segundos
			velocidad: 'fast',
			onFadeOut: function(id, actual) {
				$('#progreso li:eq(' + actual + ')').removeClass('activo');
			},
			onFadeIn: function(id, actual) {
				$('#progreso li:eq(' + actual + ')').addClass('activo');
			}
		});
*/
(function($) {
	$.fn.carrusel = function(opciones) {
		var ops = $.extend($.fn.carrusel.defaults, opciones);

		for(var i = 0, max = ops.imagenes.length; i < max; i++) {
			$('<img />').attr({
				id: 'backBuffer' + ops.id + '_' + i,
				src: ops.imagenes[i]
			}).css('display', 'none').appendTo($('body'));
		}

		ops._selector = $(this);
		$.fn.carrusel.carruseles[ops.id] = ops;

		return this.each(function() {
			var id = '#' + this.id;

			ops._timeout = setTimeout(function() {
				$.fn.carrusel.siguiente(ops.id)
			}, ops.retraso);
		});
	};

	$.fn.carrusel.defaults = {
		id: 0,
		imagenes: [],
		retraso: 5000,
		velocidad: 'slow',
		onFadeOut: function(id, actual) {},
		onFadeIn: function(id, actual) {},
		onAfterFadeIn: function(id, actual) {},
		onAfterFadeOut: function(id, actual) {},
		_actual: 0,
		_anterior: 0,
		_timeout: 0,
		_inmediato: false
	};

	$.fn.carrusel.carruseles = [];

	$.fn.carrusel.siguiente = function(id) {
		var ops = $.fn.carrusel.carruseles[id];
		$.fn.carrusel.mostrar(id, (ops._actual + 1) % ops.imagenes.length, false);
	}
	
	$.fn.carrusel.anterior = function(id) {
		var ops = $.fn.carrusel.carruseles[id];
		$.fn.carrusel.mostrar(id, (ops._actual - 1) < 0 ? ops.imagenes.length - 1 : ops._actual - 1, false);
	}

	$.fn.carrusel.mostrar = function(id, siguiente, sentido, parar) {
		var ops = $.fn.carrusel.carruseles[id];
		clearTimeout(ops._timeout);

		var imagen = ops._selector.find('img');

		ops.onFadeOut(ops.id, ops._anterior);
		imagen.fadeOut(ops.velocidad, function() {
			ops.onAfterFadeOut(ops.id, ops._anterior);

			var backBuffer = $('#backBuffer' + ops.id + '_' + siguiente);
			$(this).attr('src', backBuffer.attr('src'));

			ops.onFadeIn(ops.id, siguiente);
			$(this).fadeIn(ops.velocidad, function() {
				ops.onAfterFadeIn(ops.id, siguiente);
			}).removeAttr('id');

			ops._anterior = ops._actual;
			ops._actual = siguiente;

			if(!parar) {
				ops._timeout = setTimeout(function() {
					$.fn.carrusel.siguiente(ops.id);
				}, ops.retraso);
			}
		});
	};
})(jQuery);