(function($) {

    $.fn.slider = function(options) {
        var $this = this;
        var settings = {
            // Dimensions
            'width': this.width(),
            'height': this.height(),
            // Settings
            'wait': 4000,
            'fade': 750,
            'direction': 'right',
            'showControls': false,
            'showProgress': true,
            'hoverPause': true,
            'autoplay': false,
            'randomize': false,
            'loop': false,
            // Callbacks
            'slidebefore': function() { },
            'slideafter': function() { },
            'rewind': function() { }
        };

        var _timer = false;
        var _last = false;
        var _this = false;

        var _cycle = function() {
            clearTimeout(_timer);

            _last = _this;

            if (settings.autoplay) {
                if (settings.direction == 'right') {
                    _this = _this.prev('.jquery-slider-element');
                } else {
                    _this = _this.next('.jquery-slider-element');
                }
            }
            
            if (!_this.length) {
                _rewind();
            }

            _draw();

            if (!$this.hasClass('jquery-slider-paused') && settings.autoplay) {
                _timer = setTimeout(_cycle, settings.wait);
            }
        };

        var _rewind = function() {
            if (settings.direction == 'right') {
                _this = $this.children('.jquery-slider-element').last();
            } else {
                _this = $this.children('.jquery-slider-element').first();
            }
            settings.rewind(_this, $this);
        };

        var _draw = function() {
            $this.addClass('jquery-slider-sliding');
            if (settings.showProgress) {
                $this.find('.jquery-slider-page').removeClass('jquery-slider-page-current');
                $this.find('.jquery-slider-page:eq(' + (_this.nextAll('.jquery-slider-element').length) + ')').addClass('jquery-slider-page-current');
            }
            settings.slidebefore(_this, $this);

            if (settings.direction == 'right') {
                _this.show().css('left', -settings.width);
            } else {
                _this.show().css('left', settings.width);
            }

            _this.stop(true, true).animate({
                'left': (settings.direction == 'right' ? '+=' : '-=') + settings.width + 'px'
            }, {
                'duration': settings.fade,
                'complete': function() {
                    settings.slideafter(_this, $this);
                    $this.removeClass('jquery-slider-sliding');

                    var controls = $this.find('.jquery-slider-control');
                    var elementList = $this.children('.jquery-slider-element');

                    if (elementList.index(_this) == elementList.length - 1)
                        controls.eq(1).hide();
                    else
                        controls.eq(1).show();

                    if (elementList.index(_this) == 0)
                        controls.eq(0).hide();
                    else
                        controls.eq(0).show();

                }
            });
            if (_last) {
                _last.stop(true, true).animate({
                    'left': (settings.direction == 'right' ? '+=' : '-=') + settings.width + 'px'
                }, {
                    'duration': settings.fade
                });
            }
        };

        var _next = function() {
            if ($this.hasClass('jquery-slider-sliding')) return;
            var direction = settings.direction;
            $this.addClass('jquery-slider-paused');
            settings.direction = 'left';
            _cycle();
            settings.direction = direction;
        };

        var _prev = function() {
            if ($this.hasClass('jquery-slider-sliding')) return;
            var direction = settings.direction;
            $this.addClass('jquery-slider-paused');
            settings.direction = 'right';
            _cycle();
            settings.direction = direction;
        };

        var _init = function() {
            if (options) {
                $.extend(settings, options);
            }
            if (settings.hoverPause) {
                $this.bind({
                    'mouseenter': function() {
                        $this.addClass('jquery-slider-paused')
                        clearTimeout(_timer);
                    },
                    'mouseleave': function() {
                        $this.removeClass('jquery-slider-paused');
                        if (settings.autoplay) {
                            _timer = setTimeout(_cycle, settings.wait);
                        }
                    }
                });
            }

            var positionEls = $('<div id="menu"><ul id="minitabs"></ul></div>');
            $this.addClass('jquery-slider').width(settings.width).height(settings.height);
            $this.children().each(function() {
                var $tmp = $(this);
                _this = $(this).addClass('jquery-slider-element');
                positionEls.children('#minitabs').prepend($('<li class="jquery-slider-page">' + $(this).attr('title') + '</li>').bind('click', function() {
                    if ($this.hasClass('jquery-slider-sliding') || $(this).hasClass('jquery-slider-page-current')) return;
                    _last = _this;
                    _this = $tmp;
                    var direction = settings.direction;
                    if ($this.children().index(_last) < $this.children().index(_this))
                        settings.direction = 'left';
                    else
                        settings.direction = 'right';
                    _draw();
                    settings.direction = direction;
                }));
            });

            if (settings.showProgress) {
                $this.append(positionEls);
            }

            if (settings.showControls) {
                var controlPrev = $('<span class="jquery-slider-control jquery-slider-control-prev">&laquo;</span>').bind('click', function() { _prev(); });
                var controlNext = $('<span class="jquery-slider-control jquery-slider-control-next">&raquo;</span>').bind('click', function() { _next(); });
                $this.append(controlPrev);
                $this.append(controlNext);
            }

            if (settings.randomize) {
                _this = $this.children('.jquery-slider-element').eq(parseInt($this.children('.jquery-slider-element').length * Math.random()));
            }

            _cycle();
        };

        _init();
    };

})(jQuery);
