/**
 * zeeSlide
 * Copyright 2011, Zee Agency
 * Licensed under the CeCILL-C license
 *
 * http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
 * http://www.cecill.info/licences/Licence_CeCILL-C_V1-fr.html
 *
 * @author Julien Cabanès
 * @version 0.4
 */


(function($) {
	$.fn.slide = function(params) {

		// Configuration
		params = $.extend({

			currentClass: 		'current',
			nextClass: 			'next',
			prevClass: 			'prev',

			controlsSelector: 	'.controls > a',
			slidesSelector: 	'ol.slides > li',
			pagerSelector:		'ol.pager > li > a',
			captionsSelector: 	'ol.captions > li',

			slideSelectEvent:	'slide-select',
			slideMoveEvent:		'slide-move',
			controlsEvent:		'click',
			pagerEvent:			'click',

			endEventName:		'slide-end',
			currentSlideData:	'current-slide',

			loop: true,
			auto: false,
			interval: 5000,

			// this = $slides
			getCurrent: function() {
				return this.filter('.'+params.currentClass);
			},

			// this = $slides
			// Starts at 1
			getById: function(id) {
				return this.filter(':nth-child('+id+')');
			},

			// this = current slide
			getFuture: function(direction, loop) {
				var $future = this[direction]();

				if(!$future.length && loop) {
					$future = this.siblings((direction === 'next' ? ':first' : ':last')+'-child');
				}

				return $future;
			},

			// this = current slide
			getSiblings: function(direction) {
				return this[!direction ? 'siblings' : direction+'All']();
			},

			// this = a
			getPagerId: function() {
				return this.parent().prevAll().length + 1;
			},

			// this = $pager
			pagerCallback: function($current) {
				this.parent()
					.filter(':nth-child('+($current.prevAll().length+1)+')')
					.activate();
			},

			// this = $captions
			captionCallback: function($current) {
				this.filter(':nth-child('+($current.prevAll().length+1)+')')
					.activate();
			},

			// this = $controls
			checkArrow: function($current, direction) {
				direction = direction || 'next';
				this.filter('.'+params[direction+'Class'])
					[params.getSiblings.call($current, direction).length ? 'enable' : 'disable']();
			},

			// this = $slideshow
			callback: function($slideshow) {

			}
		}, params);

		return this.each(function() {

			// Caching
			var $slideshow = $(this),
				timer,
				direction,
				$a,
				$current,
				$future,
				$controls = 	$slideshow.find(params.controlsSelector),
				$slides = 		$slideshow.find(params.slidesSelector),
				$pager = 		$slideshow.find(params.pagerSelector),
				$captions = 	$slideshow.find(params.captionsSelector),

				antiPrevClass = params.currentClass+' '+params.nextClass,
				antiNextClass = params.currentClass+' '+params.prevClass,
				antiCurrentClass = params.nextClass+' '+params.prevClass,


				zIndex = 		1000,
				$current = 		params.getCurrent.call($slides),
				autoNext = function(e) {
					clearTimeout(timer);
					timer = setTimeout(function() {
						if($slideshow.data('auto')) {
							$controls.filter('.'+params.nextClass).trigger(params.controlsEvent);
						}
					}, $slideshow.data('interval'));
				};

			// Public
			$slideshow	.data('loop', !$slideshow.hasClass('no-loop') && params.loop)
						.data('auto', $slideshow.hasClass('auto') || params.auto)
						.data('interval', $slideshow.data('interval') || params.interval);


			// Reorder slides
			/** /
			if(!$slideshow.hasClass('sheet-left')
				&& !$slideshow.hasClass('sheet-down')
				&& !$slideshow.hasClass('sheet-up'))
			{
				$slides.each(function() {
					$(this).css('z-index', zIndex--);
				});
			}
			/**/

			// Do What BackEnd Dev Didn't
			if(!$current.length) {
				$current = $slides.filter(':first-child').addClass(params.currentClass);
			}

			$current.nextAll().removeClass(antiNextClass).addClass(params.nextClass);



			// Controls
			$controls.bind(params.controlsEvent, function(e) {
				e.preventDefault();

				$a = $(this);
				direction = $a.hasClass(params.nextClass) ? 'next' : 'prev';
				$current = params.getCurrent.call($slides);
				$future = params.getFuture.call($current, direction, $slideshow.data('loop'));

				if(!$future.length) {
					$slideshow.trigger(params.endEventName, direction);
				} else {
					$future.trigger(params.slideMoveEvent, direction);
				}
			});

			// Auto Next
			if($slideshow.data('auto')) {
				$controls.bind(params.controlsEvent, autoNext);
				autoNext();
			}

			// Slide Event
			$slides.bind(params.slideMoveEvent, function(e) {

				e.preventDefault();
/*
				e.stopPropagation();
				e.stopImmediatePropagation();
*/

				$current = $(this);

				// Before current
				params.getSiblings.call($current, 'prev')
					.removeClass(antiPrevClass)
					.addClass(params.prevClass);

				// After current
				params.getSiblings.call($current, 'next')
					.removeClass(antiNextClass)
					.addClass(params.nextClass);

				// Current
				$current.removeClass(antiCurrentClass)
						.addClass(params.currentClass);

				// Could be useful Info
				$slideshow.data(params.currentSlideData, $current.prevAll().length+1);

				/* Prototype of JS animation fallback * /
				params.getSiblings.call($current, 'prev')
					.removeClass(antiPrevClass)
					.addClass(params.prevClass)
					.animate({left: '-100%'}, 500);

				params.getSiblings.call($current, 'next')
					.removeClass(antiNextClass)
					.addClass(params.nextClass)
					.animate({left: '100%'}, 500);


				// Future becomes Current
				$current.removeClass(antiCurrentClass)
						.addClass(params.currentClass)
						.animate({left: 0}, 500);
				/**/

				params.pagerCallback.call($pager, $current);

				params.captionCallback.call($captions, $current);

				if(!$slideshow.data('loop')) {
					params.checkArrow.call($controls, $current, 'prev');
					params.checkArrow.call($controls, $current, 'next');
				}

				params.callback.call($slideshow, $current);
			});

			$slideshow.bind(params.slideSelectEvent, function(e, slideId) {
				e.preventDefault();

				if(slideId) {
					params.getById.call($slides, slideId).trigger(params.slideMoveEvent);
				}
			});

			// Do what BackEnd Dev didn't
			$slides.filter('.current').trigger(params.slideMoveEvent);

			// Paging
			$pager.bind(params.pagerEvent, function(e) {

				e.preventDefault();

				params.getById.call($slides, params.getPagerId.call($(this))).trigger(params.slideMoveEvent);
			});
		});
	};
})(jQuery);
