(function ($) {

	var defaults = {
			synchro: false,
			noLock: false,
			uniqId: 0,
			initOffset: 0,
			duration: 1500
	}
	
	$.fn.FBSlider = function(o) {
        if (typeof o == 'string') {
            var instance = $(this).data('FBSlider'), args = Array.prototype.slice.call(arguments, 1);
            if (instance.options.synchro || $(this).size() <= 1) {
            	return instance[o].apply(instance, args);
            } else {
            	return $(this).each(function () {
            		var instance = $(this).data('FBSlider');
            		instance[o].apply(instance, args);
            	});
            }
        } else {
        	var those = this;
            return this.each(function() {
                var instance = $(this).data('FBSlider');
                if (instance) {
                    if (o) {
                        $.extend(instance.options, o);
                    }
                    instance.reload();
                } else {
                    $(this).data('FBSlider', new $.FBSlider(this, o, those));
                }
            });
        }
    };

    /**
     * The FBSlider object.
     *
     * @constructor
     * @class fbSlider
     * @param e {HTMLElement} The element to create the slider for.
     * @param o {Object} A set of key/value pairs to set as configuration properties.
     * @cat Plugins/FBSlider
     */
    $.FBSlider = function(e, o, those) {
        this.options    = $.extend({}, defaults, o || {});

        if (!this.options.synchro) {
        	defaults.uniqId++;
        }	
        this.uniqId = 0 + defaults.uniqId;
        var id = defaults.uniqId;
        this.clip            = null;
        this.list            = null;
        this.those			 = those;

        this.wh = 'width';
        this.lt = 'left';

        if (e.nodeName.toUpperCase() == 'UL' || e.nodeName.toUpperCase() == 'OL') {
            this.list      = $(e);
        } else {
            this.list      = $(e).find('ul,ol').eq(0);
        }

        
        this.clip = this.list.wrap('<div></div>').parent();

        
        this.clip.addClass('FBSlider-wrapper-'+id).css({
            position: 'relative',
            overflow: 'hidden',
            padding : 0
        });

        this.list.addClass('FBSlider-list-'+id).css({
            position: 'relative',
            top: 0,
            margin: 0,
            padding: 0,
            left: 0
        });
        
        var li = this.list.children('li');
        var di = null;
        
        var self = this;

        if (li.size() > 0) {
            var wh = 0, j = 0;
            li.each(function() {
                self.format(this,id, j++);
                wh += self.dimension(this, di);
            });

            this.list.css(this.wh, wh + 'px');

            // Only set if not explicitly passed as option
            if (!o || o.size === undefined) {
                this.options.size = li.size();
            }
        }
        var ctwidth = this.clip.parent().width();
        

        this.clip.css('display', 'block');
        // fix ie6
        if (ctwidth && ctwidth>0) {
        	this.clip.css('width',''+ctwidth+'px');
        }
    };
    
    var $FBs = $.FBSlider;
    $FBs.fn = $FBs.prototype = {};
    	
    $FBs.fn.extend = $FBs.extend = $.extend;
    
    $FBs.fn.extend({
    	
    	locked: false,
    	
    	scrollLeft: function (nbDecal,onComplete) {
			if (onComplete == null) {
				onComplete = function () {};
			}
	    	if (this.options.noLock || !this.locked) {
				try {
					this.locked=true;
					var ul = null;
					if (this.options.synchro) {
						ul = $(this.those);
					}
					else {
						ul = $(this.list);
					}
					var ulSize = ul.outerWidth();
					var containerSize = $(this.clip).width();
					var eltSize = $(this.list).find('.FBSlider-item').outerWidth(true);
					var csteDiff = containerSize % eltSize;
					var decal = $FBs.intval(ul.css('left').replace('px','').replace('auto','0')) - eltSize;
					nbDecal--;
					while ( ((ulSize + decal - eltSize - containerSize) + csteDiff >= 0) && (nbDecal > 0)) {
						nbDecal--;
						decal = decal - eltSize;
					}
					var that = this;
					if ((ulSize + decal - containerSize) + csteDiff >= 0 ) {
						var moreLeft = true;
						var moreRight = true;
						if ((ulSize + decal - containerSize) + csteDiff <= 0) {
							moreRight = false;
						}
						ul.animate({left: ''+decal+'px'},this.options.duration,'swing',function() { that.locked = false; onComplete.apply(ul,[ moreLeft,moreRight ]); });
					} else {
						this.locked=false;
					}
				} catch (e) {
					this.locked=false;
				}
			}
    	},

    	scrollRight: function (nbDecal,onComplete) {
    		if (onComplete == null) {
    			onComplete = function () {};
    		}
	    	if (this.options.noLock || !this.locked) {
				try {
					this.locked=true;
					
					var ul = null;
					if (this.options.synchro) {
						ul = $(this.those);
					}
					else {
						ul = $(this.list);
					}
					var containerSize = $(this.clip).width();
					var eltSize = $(this.list).find('.FBSlider-item').outerWidth(true);
					var decal = $FBs.intval(ul.css('left').replace('px','').replace('auto','0')) + eltSize;
					nbDecal--;
					while ( (decal + eltSize) <= 0 && nbDecal > 0) {
						nbDecal--;
						decal = decal + eltSize;
					}
					var that = this;
					if (decal <= 0) {
						var moreLeft = true;
						var moreRight = true;
						if (decal >= 0) {
							moreLeft = false;
						}
						ul.animate({left: ''+decal+'px'},this.options.duration,'swing', function () { that.locked = false; onComplete.apply(ul, [ moreLeft,moreRight ]); });
					} else {
						this.locked=false;
					}
				} catch (e) {
					this.locked=false;
				}
			}
    	},
    	
    	scrollTo : function (n,onComplete) {
			var ul = null;
			if (this.options.synchro) {
				ul = $(this.those);
			}
			else {
				ul = $(this.list);
			}
			
			var ulSize = ul.outerWidth();
			var containerSize = $(this.clip).width();
			var eltSize = $(this.list).find('.FBSlider-item').outerWidth();
			var decal = $FBs.intval(ul.css('left').replace('px','').replace('auto','0'));
			var currentId = decal != 0 ? Math.floor( Math.abs(decal) / eltSize ) : 0;
			if (n > currentId) {
				this.scrollLeft(n-currentId,onComplete);
			} else {
				this.scrollRight(currentId-n,onComplete);
			}
    	},
    	
        format: function(e, id ,i) {
            e = $(e);
            var split = e.get(0).className.split(' ');
            for (var j = 0; j < split.length; j++) {
                if (split[j].indexOf('FBSlider-') != -1) {
                    e.removeClass(split[j]);
                }
            }
            e.addClass('FBSlider-item').addClass('FBSlider-'+id+'-item-' + i).css({
                'float': 'left',
                'list-style': 'none'
            }).attr('FBSliderIndex', i);
            return e;
        },

        dimension: function(e, d) {
            var el = $(e);

            if (d == null) {
                return (el.outerWidth(true) || el.getHiddenDimensions(true).outerWidth || $FBs.intval(this.options.defaultItemWidth) )
            } else {
                var w = d - $FBs.intval(el.css('marginLeft')) - $FBs.intval(el.css('marginRight'));
                $(el).css('width', w + 'px');
                return this.dimension(el);
            }
        }
    });

    $FBs.extend({

        intval: function(v) {
            v = parseInt(v, 10);
            return isNaN(v) ? 0 : v;
        }

    });
})(jQuery);


/**
 * JQuery width/height 0 on hidden elements Fix
 * 
 * see: http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/
 * 
 */
(function($) {
$.fn.getHiddenDimensions = function(includeMargin) {
    var $item = this,
        props = { position: 'absolute', visibility: 'hidden', display: 'block' },
        dim = { width:0, height:0, innerWidth: 0, innerHeight: 0,outerWidth: 0,outerHeight: 0 },
        $hiddenParents = $item.parents().andSelf().not(':visible'),
        includeMargin = (includeMargin == null)? false : includeMargin;
 
    var oldProps = [];
    $hiddenParents.each(function() {
        var old = {};
 
        for ( var name in props ) {
            old[ name ] = this.style[ name ];
            this.style[ name ] = props[ name ];
        }
 
        oldProps.push(old);
    });
 
    dim.width = $item.width();
    dim.outerWidth = $item.outerWidth(includeMargin);
    dim.innerWidth = $item.innerWidth();
    dim.height = $item.height();
    dim.innerHeight = $item.innerHeight();
    dim.outerHeight = $item.outerHeight(includeMargin);
 
    $hiddenParents.each(function(i) {
        var old = oldProps[i];
        for ( var name in props ) {
            this.style[ name ] = old[ name ];
        }
    });
 
    return dim;
}
}(jQuery));
