(function ($) {
    var s = [];
    function getDefault(t) {
        if (t == 1) {
            return {
                hover: {
                    amount: 2,
                    speed: 100
                },
                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 () {
            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);
                if (offset <= -set.size) {
                    $("li:first", o).appendTo(o);
                    o.css(type, offset + set.size)
                }
            } else {
                o.css(type, offset + set.amount);
                if (offset >= 0) {
                    $("li:last", o).prependTo(o);
                    o.css(type, offset - set.size)
                }
            }
            scroll(o, set)
        },
		set.speed)
    }
    function copy(set) {
        var a = {};
        $.each(set,
		function (i, n) {
		    a[i] = n
		});
        return a
    }
})($);
