(function ($) {
    var defaults = {
        slides: null,
        type: 'fade',
        speed: 'slow',
        delay: null,
        direction: 'right',
        switcher: true,
        switcherTextLeft: '<<',
        switcherTextRight: '>>',
        mouseOverStop: true,
        mouseOutInstantStart: false,
        speedIn: null,
        speedOut: null,
        startIndex: 'first'
    },
        opts = {},
        me = [],
        items = [],
        count = [],
        idx = [],
        lastIdx = [],
        interval = [],
        delay = [],
        plugin = {
            initialize: function (object, options) {
                opts = options ? $.extend({}, defaults, options) : defaults;
                opts.speedIn = opts.speedIn || opts.speed;
                opts.speedOut = opts.speedOut || opts.speed;
                return object.each(function (index) {
                    me[index] = $(this), items[index] = me[index].children(opts.slides), count[index] = items[index].length, interval[index] = null;
                    switch (opts.startIndex) {
                    default:
                        if (opts.startIndex.toString().search(/^-?[0-9]+$/) != 0) {
                            idx[index] = 0;
                            break
                        }
                        idx[index] = opts.startIndex;
                        break;
                    case 'first':
                        idx[index] = 0;
                        break;
                    case 'last':
                        idx[index] = count[index] - 1;
                        break;
                    case 'random':
                        idx[index] = Math.floor(Math.random() * count[index]);
                        break
                    }
                    lastIdx[index] = idx[index];
                    if (count[index] <= 1) {
                        return
                    }
                    delay[index] = opts.delay === null ? count[index] * 1000 : opts.delay;
                    me[index].css('position', 'relative');
                    items[index].each(function (slideIndex) {
                        $(this).css({
                            position: 'absolute',
                            top: 'auto',
                            left: 'auto',
                            zIndex: (count[index] * 10) - (slideIndex * 10)
                        })
                    });
                    if (opts.switcher) {
                        me[index].append('<div class="slide-query-switcher"><div class="slide-query-switcher-left"></div><div class="slide-query-switcher-right"></div></div>');
                        var zIndexTop = (count[index] + 1) * 10;
                        $.extend(opts.switcherStyleLeft, {
                            zIndex: zIndexTop
                        });
                        $.extend(opts.switcherStyleRight, {
                            zIndex: zIndexTop
                        });
                        $('.slide-query-switcher-left', me[index]).html(opts.switcherTextLeft).css({
                            position: 'absolute',
                            bottom: 0,
                            left: 0
                        }).bind('click', function () {
                            plugin.change(index, 'left')
                        });
                        $('.slide-query-switcher-right', me[index]).html(opts.switcherTextRight).css({
                            position: 'absolute',
                            bottom: 0,
                            right: 0
                        }).bind('click', function () {
                            plugin.change(index, 'right')
                        })
                    }
                    items[index].hide();
                    plugin.animation(items[index].eq(idx[index]).addClass('slide-query-active-item'), opts.speedIn);
                    plugin.start(index);
                    if (opts.mouseOverStop) {
                        me[index].hover(function () {
                            clearInterval(interval[index])
                        }, function () {
                            if (opts.mouseOutInstantStart) {
                                plugin.change(index, opts.direction)
                            }
                            plugin.start(index)
                        })
                    }
                })
            },
            start: function (index) {
                interval[index] = setInterval(function () {
                    plugin.change(index, opts.direction)
                }, delay[index])
            },
            change: function (index, direction) {
                var lastSlide = count[index] - 1;
                switch (direction) {
                default:
                case 'right':
                    idx[index] = idx[index] == lastSlide ? 0 : idx[index] + 1;
                    break;
                case 'left':
                    idx[index] = idx[index] == 0 ? lastSlide : idx[index] - 1;
                    break;
                case 'random':
                    var random = Math.floor(Math.random() * count[index]);
                    if (lastIdx[index] == random) {
                        return plugin.change(index, 'random')
                    }
                    idx[index] = random;
                    break
                }
                lastIdx[index] = idx[index];
                plugin.animation(items[index].filter('.slide-query-active-item').removeClass('slide-query-active-item'), opts.speedOut);
                plugin.animation(items[index].eq(idx[index]).addClass('slide-query-active-item'), opts.speedIn)
            },
            animation: function (element, speed, callback) {
                switch (opts.type) {
                default:
                case 'none':
                    return element.toggle(0, callback);
                case 'fade':
                    return element.animate({
                        opacity: 'toggle'
                    }, speed, function () {
                        if ($.isFunction(callback)) {
                            callback.call(element)
                        }
                        if (element[0].style.removeAttribute) {
                            element[0].style.removeAttribute('filter')
                        }
                    });
                case 'slide':
                    return element.slideToggle(speed, callback)
                }
            }
        };
    $.fn.extend({
        slideQuery: function (options) {
            plugin.initialize(this, options)
        }
    })
})(jQuery);
