(function($) {
    var s = [];

    //默认设置
    function getDefault(t) {
        if (t == 1) {
            return {
                hover: {
                    amount: 2,
                    speed: 10
                },
                mousedown: {
                    amount: 5,
                    speed: 5
                }
            }
        }
        return {
            amount: 1,
            speed: 20,
            hover: true,
            direction: 'left'
        };
    }

    //入口
    $.fn.fxMarquee = function(set, next, prev) {
        setting = $.extend(getDefault(), set);

        this.each(function() {
            $.fxMarquee($("ul,ol", this), set, next, prev);
        });
    };

    //主体。也可以通过该方法来绑定页面元素
    $.fxMarquee = function(o, set, next, prev) {

        o = $(o);

        set = init(o, set);

        //复制一遍需要滚动的内容
        o.html(o.html() + o.html()).css({ left: 0, top: 0 });

        //绑定移上事件。移上后停止滚动，离开继续
        if (set.hover) {
            $('li', o).mouseover(function() {
                stop(set.index);
            }).mouseleave(function() {
                scroll(o, set);
            })
        }

        //绑定按钮
        for (var i = 2; i < arguments.length; i++) {
            fastEvent(o, set, arguments[i]);
        }
        //开始滚动
        scroll(o, set);
    };

    //初始化
    function init(o, set) {

        set = $.extend(getDefault(), set);

        o = $(o);

        if (o.attr('fxMarquee'))
            set.index = parseInt(o.attr('fxMarquee'));
        else {
            set.index = $("*").index(o);
            o.attr('fxMarquee', set.index);
        }
        set.refer = set.direction == 'up' || set.direction == 'down' ? 'top' : 'left';
        set.size = set.refer == 'top' ? $("li", o).outerHeight({ margin: true }) : $("li", o).outerWidth({ margin: true });

        return set;
    }

    //前进后退按钮的事件绑定
    function fastEvent(o, set, fset) {

        var d = getDefault(1);

        if (typeof (fset) == 'string') {
            fset = $.extend(getDefault(1), { object: fset });
        }
        else if (fset && fset.object && !fset.hover && !fset.mousedown) {
            fset.hover = d.hover;
            fset.mousedown = d.mousedown;
        }
        if (fset && fset.object) {
            //初始化参数
            var o2 = $(fset.object);

            if (fset.hover)
                fset.hover = $.extend(d.hover, fset.hover);
            if (fset.mousedown)
                fset.mousedown = $.extend(d.mousedown, fset.mousedown);

            fset.direction = fset.type == 'back' ? set.refer == 'top' ? 'up' : 'right' : set.refer == 'top' ? 'down' : 'left';

            $.each(['hover', 'mousedown'], function(i, n) {
                if (fset[n]) {
                    fset[n].direction = fset.direction;
                    o2.bind(n == 'hover' ? 'mouseover' : 'mousedown', function() {
                        scroll(o, $.extend(copy(set), fset[n]));
                    }).bind(n == 'hover' ? 'mouseleave' : 'mouseup', function() {
                        scroll(o, set);
                    });
                }
            });
        }
    }

    //停止滚动
    function stop(i) {
        if (!!s[i]) clearTimeout(s[i]);
    }

    //滚动
    function scroll(o, set) {     

        stop(set.index);
        s[set.index] = setTimeout(function() {
            // 判断是left还是top
            var type = set.direction == 'up' || set.direction == 'down' ? 'top' : 'left';
            // 获取值
            var offset = parseInt(o.css(type));
            if (set.direction == 'left' || set.direction == 'up') {
                o.css(type, offset - set.amount);
            }
            else {
                if (offset < 0) {
                    o.css(type, offset + set.amount);
                }
            }
            scroll(o, set);
        }, set.speed);
    }

    //复制对象
    function copy(set) {
        var a = {};
        $.each(set, function(i, n) {
            a[i] = n;
        });
        return a;
    }

})($);
