﻿/**
 * Copyright (c) 2011 Sylvain Gougouzian (sylvain@gougouzian.fr) MIT
 * (http://www.opensource.org/licenses/mit-license.php) licensed. GNU GPL
 * (http://www.gnu.org/licenses/gpl.html) licensed.
 */
jQuery(function($) {
	$.fn.moodulite = function(options) {
		var el = new Array();
		var opts = $.extend( {}, $.fn.moodulite.defaults, options);
		var ctrls = $.extend( {}, $.fn.moodulite.controls);
		var effects = $.extend( {}, $.fn.moodulite.effects);
		this.each(function(i) {
			el[i] = new $moodulite(this, opts, ctrls, effects);
		});
		return opts.api ? (el.length == 1 ? el[0] : el) : null;
	};
	$.moodulite = function(e, opts, ctrls, effects) {
		this.e = $(e);
		if (opts.random) {
			var elems = $('> ' + opts.item, this.e);
			elems.sort(function() {
				return (Math.round(Math.random()) - 0.5);
			});
			this.e.html('');
			for ( var i = 0; i < elems.length; i++)
				this.e.append(elems[i]);
		}
		this.aItems = $('> ' + opts.item, this.e);
		this.aItems.each(function(i) {
			$(this).attr('data-position', i);
		});
		this.nbItems = this.aItems.length;
		this.current = 0;
		this.dir = 1;
		this.locked = false;
		this.temp = new Array();
		this.timerMoving = null;
		this.opts = opts;
		this.controls = ctrls;
		this.effects = effects;
		if (this.nbItems > 1)
			this._init();
	};
	var $moodulite = $.moodulite;
	$moodulite.fn = $moodulite.prototype = {
		moodulite : '1.0'
	};
	$moodulite.fn.extend = $moodulite.extend = $.extend;
	$moodulite.fn.extend( {
		_init : function() {
			var self = this;
			this.e.wrap('<div></div>');
			this.e.parent().css( {
				'position' : 'relative',
				'overflow' : 'hidden',
				'width' : this.e.width(),
				'height' : this.e.height()
			});
			this.e.css( {
				'position' : 'absolute',
				'left' : 0,
				'top' : 0
			});
			this.control = this.opts.controls.split(' ');
			this.effect = this.opts.effects.split(' ');
			this._resize();
			if (this.opts.percentSize != 0) {
				$(window).bind('resize', function() {
					self._resizePercent();
				});
			}
			var i;
			$('>' + this.opts.item + ':first', this.e).addClass('current');
			for (i = 0; i < this.control.length; i++) {
				if ($.isFunction(this.controls.init[this.control[i]]))
					this.controls.init[this.control[i]](this);
			}
			for (i = 0; i < this.effect.length; i++) {
				if ($.isFunction(this.effects.init[this.effect[i]]))
					this.effects.init[this.effect[i]](this);
			}
			if (this.opts.auto) {
				this.timerMoving = setTimeout(function() {
					self.next();
				}, self.opts.dispTimeout);
			}
		},
		_resize : function() {
			var i;
			for (i = 0; i < this.effect.length; i++) {
				if ($.isFunction(this.effects.resize[this.effect[i]]))
					this.effects.resize[this.effect[i]](this);
				else {
					this.size = parseInt(this.e.parent().width());
					this.e.width(2 * this.size + 'px');
					$('> ' + this.opts.item, this.e).width(this.size);
				}
			}
		},
		_resizePercent : function() {
			var tmp = this.e.parent().parent().width();
			this.e.parent().width(tmp * this.opts.percentSize);
			this._resize();
		},
		_move : function() {
			var i;
			for (i = 0; i < this.control.length; i++) {
				if ($.isFunction(this.controls.before[this.control[i]]))
					this.controls.before[this.control[i]](this);
			}
			for (i = 0; i < this.effect.length; i++) {
				if ($.isFunction(this.effects.before[this.effect[i]]))
					this.effects.before[this.effect[i]](this);
			}
			var self = this;
			if ($.isFunction(this.opts.move)) {
				this.opts.move(this, function() {
					self._afterMoving();
				});
			} else {
				this._afterMoving();
			}
		},
		_afterMoving : function() {
			var self = this;
			for (i = 0; i < this.control.length; i++) {
				if ($.isFunction(this.controls.after[this.control[i]]))
					this.controls.after[this.control[i]](this);
			}
			for (i = 0; i < this.effect.length; i++) {
				if ($.isFunction(this.effects.after[this.effect[i]]))
					this.effects.after[this.effect[i]](this);
			}
			for (i = 0; i < this.opts.callbacks.length; i++) {
				this.opts.callbacks[i](this);
			}
			this.locked = false;
			this.dir = 1;
			if (this.opts.auto) {
				this.timerMoving = setTimeout(function() {
					self.next();
				}, this.opts.dispTimeout);
			}
		},
		start : function() {
			if (!this.opts.auto) {
				this.locked = false;
				this.opts.auto = true;
				this.next();
			}
			return false;
		},
		stop : function() {
			clearTimeout(this.timerMoving);
			this.opts.auto = false;
			this.locked = false;
			return false;
		},
		next : function() {
			this.moveTo(this.current + 1);
			return false;
		},
		prev : function() {
			this.dir = -1;
			this.moveTo(this.current - 1);
			return false;
		},
		moveTo : function(n) {
			if (!this.locked) {
				this.locked = true;
				clearTimeout(this.timerMoving);
				if (n >= this.nbItems)
					n -= this.nbItems;
				if (n < 0)
					n += this.nbItems;
				this.current = n;
				this._move();
			}
		}
	});
	$.fn.moodulite.defaults = {
		item : 'li',
		controls : '',
		effects : 'left',
		easing : '',
		auto : true,
		speed : 2000,
		dispTimeout : 1000,
		callbacks : [],
		random : false,
		percentSize : 0,
		api : false
	};
	$.fn.moodulite.controls = {
		callback : {}
	};
	$.fn.moodulite.effects = {
		init : {
			left : function(m) {
				m.opts.move = function(c, b) {
					c.e.animate( {
						left : (c.dir == 1 ? '-=' : '+=') + c.size + 'px'
					}, c.opts.speed, c.opts.easing, function() {
						b();
					});
				}
			}
		},
		before : {
			left : function(m) {
				if (m.dir == -1) {
					m.e.prepend($('> ' + m.opts.item + ':last', m.e));
					m.e.css('left', '-' + m.size + 'px');
				} else {
					$('>' + m.opts.item + '[data-position=' + m.current + ']', m.e).insertAfter($('>' + m.opts.item + ':first', m.e));
				}
			}
		},
		after : {
			left : function(m) {
				if (m.dir == 1) {
					m.e.append($('> ' + m.opts.item + ':first', m.e));
					m.e.css('left', 0);
				}
			}
		},
		resize : {}
	};
	$.fn.moodulite.controls = {
		init : {},
		before : {},
		after : {}
	};
});
