(function(){
    var animateBox = function(items, options){
        var
        defaults = {
            nextbutton : null,
            prevbutton : null,
            autoanimate : false,
            timeout : 5000,
            speed : 1500
        },
        data = $(items),
        s = $.extend(s, defaults, options),
        current = 0,
        animating = false,
        timeOut = null,
        autoanimate = false,
        animatenext = 0,
        itemWidth = 0,
        dataLength = data.length,
        onAnimationEnd = null,
        //    prevEasing = 'swing',

        set_timeout = function (toNext) {
            var ttime =  s.timeout;
            if($(data.get(current)).find('input[name="duration"]').length > 0) {
                ttime = parseInt(parseFloat($(data.get(current)).find('input[name="duration"]').val()) * 100);
            }
            if (timeOut)
                clearTimeout(timeOut);
            timeOut = setTimeout(function(){
                animate(toNext)
            }, ttime);
        },

        setAutoanimate = function(set) {
            if (set) {
                autoanimate = true;
                set_timeout(true);
            } else {
                autoanimate = false;
                clearTimeout(timeOut);
            }
        },

        animate = function(toNext, fromUser) {
            if (animating)  {
                if (toNext && animatenext < dataLength - 1 && fromUser)
                    animatenext++;
                else if (!toNext && animatenext > -dataLength + 1 && fromUser)
                    animatenext--;
                else if (!fromUser)
                    set_timeout(toNext)
            } else {
                animating = true;
                animateTo(toNext);
            }
        },
        endAnimate = function() {
            if (onAnimationEnd)
                onAnimationEnd.call(items, current);
            animating = false;
            if (animatenext != 0) {
                animate(animatenext > 0);
                animatenext > 0? animatenext-- : animatenext++;
            } else if (autoanimate)
                set_timeout(true);
        },
        animateTo = function(toNext) {
            var
            fc,
            ended = 0,
            endedEx,
            animateItem = function(item, margin) {
                $(item).animate({
                    marginLeft: margin + 'px'
                },
                s.speed, ifended);
            },
            ifended = function () {
                ended++;
                if (ended == 2) {
                    $(data.get(current)).hide().css('marginLeft', '0px');
                    endedEx();
                    endAnimate();
                }
            }
            switch (true) {
                // to first
                case current == dataLength - 1 && toNext:
                    endedEx = function(){
                        current = 0;
                        $(data.get(0)).show();
                        fc.remove();
                    }
                    fc = $(data.get(0)).clone().appendTo(data.parent()).css('marginLeft', itemWidth + 'px').show();
                    animateItem(fc, 0);
                    animateItem(data.get(current), -itemWidth);
                    break;
                // to last
                case current == 0 && !toNext:
                    endedEx = function(){
                        current = dataLength - 1;
                        $(data.get(dataLength - 1)).show();
                        fc.remove();
                    }
                    fc = $(data.get(dataLength - 1)).clone().insertBefore(data.get(0)).css('marginLeft', '-' + itemWidth + 'px').show();
                    animateItem(fc, 0);
                    animateItem(data.get(current), itemWidth);
                    break;
                case toNext:
                    endedEx = function(){
                        current++;
                    }
                    $(data.get(current + 1)).css('marginLeft', itemWidth + 'px').show();
                    animateItem(data.get(current + 1), 0);
                    animateItem(data.get(current), -itemWidth);
                    break;
                case !toNext:
                    endedEx = function(){
                        current--
                    }
                    $(data.get(current - 1)).css('marginLeft', '-' + itemWidth + 'px').show();
                    animateItem(data.get(current - 1), 0);
                    animateItem(data.get(current), itemWidth);
                    break;
            }
        };

        if (dataLength > 1) {
            itemWidth = $(data.get(0)).width()
            if (s.autoanimate) {
                setAutoanimate(true);
                data.parent()
                .mouseenter(function(){
                    setAutoanimate(false);
                })
                .mouseleave(function(){
                    setAutoanimate(true);
                });
            }
            if (s.nextbutton) {
                $(s.nextbutton).click(function(e) {
                    e.preventDefault();
                    animate(true, true);
                });
            }
            if (s.prevbutton) {
                $(s.prevbutton).click(function(e) {
                    e.preventDefault();
                    animate(false, true);
                });
            }
        }

        return {
            navigate : function(to) {
                if (to >= 0 && to < dataLength && to != current) {
                    if (to > current)
                        animatenext = to - current;
                    else
                        animatenext = to - current;
                    animate(animatenext > 0);
                    animatenext > 0? animatenext-- : animatenext++;
                }
                return this;
            },
            animated : function(callback) {
                if (callback && $.isFunction(callback))
                    onAnimationEnd = callback;
                return this;
            },
            autoanimate : function(set) {
                setAutoanimate(set? true : false);
                return this;
            }
        }
    };
    $.fn.bannerslider = function(options){
        if (!this.animateBox)
            this.animateBox = new animateBox(this, options);
        return this.animateBox;
    };

})(jQuery);
