(function($) {
    $.fn.horizontalPager = function(settings) {
        settings = $.extend({
            pagerButtonsContainerClass: 'pager-buttons-container',
            prevButtonText: 'previous',
            nextButtonText: 'next',
            prevButtonClass: 'pager-prev',
            nextButtonClass: 'pager-next',
            pageOffset: 20,
            sliderFilter: null,
            containerFilter: null,
            insertPagingButtonsAfter: null,
            uid: _generateUid(),
            createSliderAndContainer: false,
            containerWidth: 0,
            handleResize: true
        }, settings);

        var matches = this;
        var visiblePageIndex = 0;
        var _swappingPages = false;
        var slider = null, container = null, containerPrototype = null, placeholder = null;
        if (!!settings.createSliderAndContainer && matches.length > 0) {
            slider = $('<div id="' + settings.uid + '_slider" />');
            container = $('<div id="' + settings.uid + '_container" />');
            $(this[0]).prev().before(container);
            if (!!settings.containerFilter) {
                containerPrototype = !!settings.containerFilter ? container.parents(settings.containerFilter) : container.parent();
                var height = 0;
                for (var i = 0; i < matches.length; i++) {
                    height = Math.max(height, $(matches[i]).height());
                }
                var width = (!!settings.containerWidth ? settings.containerWidth : containerPrototype.width());
                container.css({ position: 'absolute', width: width + 'px', height: height + 'px' });
                placeholder = $('<div />');
                placeholder.css({ height: height + 'px' });
                container.after(placeholder);
            }
            container.append(slider);
            this.each(function(i, el) {
                $(el).data('moduleid', $(el).prev().attr('name')).data('index', i);
            });
            this.appendTo(slider);
        } else {
            slider = this.length > 0 ? (!!settings.sliderFilter ? $(this[0]).parents(settings.sliderFilter) : $(this[0]).parent()) : null;
            container = !!slider ? (!!settings.containerFilter ? slider.parents(settings.containerFilter) : slider.parent()) : null;
        }
        var pageWidth = 0;

        function _initialize() {
            if (matches.length <= 0)
                return;

            pageWidth = container.width();
            container.css({ overflow: 'hidden' });
            slider.css({ position: 'absolute', top: '0px', left: '0px' });

            for (var i = 0; i < matches.length; i++) {
                var $el = $(matches[i]);
                $el.css({ position: 'absolute', width: pageWidth + 'px', left: ((pageWidth + settings.pageOffset) * i) + 'px', top: '0px' });
                var contentMenuEntry = $('#cn-' + $el.data('moduleid'));
                contentMenuEntry.data('index', $el.data('index')).click(function(event) { event.preventDefault(); _swapPages($(this).data('index')); });
                if (!i)
                    contentMenuEntry.addClass('highlight');
            }
            (placeholder || container).after('<div class="' + settings.pagerButtonsContainerClass + '"><a id="' + settings.uid + '-prev" class="' + settings.prevButtonClass + '" href="#">' + settings.prevButtonText + '</a><a id="' + settings.uid + '-next" class="' + settings.nextButtonClass + '" href="#">' + settings.nextButtonText + '</a></div>');
            $('#' + settings.uid + '-prev').click(_prevClicked);
            $('#' + settings.uid + '-next').click(_nextClicked);
            _showHidePagerLinks();
            if (!!settings.handleResize) $(window).resize(_windowResized);
        }

        function _windowResized() {
            if (settings.createSliderAndContainer && !!containerPrototype) {
                container.css({ width: containerPrototype.width() + 'px' });
            }
            pageWidth = container.width();
            for (var i = 0; i < matches.length; i++) {
                $(matches[i]).css({ position: 'absolute', width: pageWidth + 'px', left: ((pageWidth + settings.pageOffset) * i) + 'px', top: '0px' });
            }
            slider.css({ left: -((pageWidth + settings.pageOffset) * visiblePageIndex) + 'px' });
        }

        function _showHidePagerLinks() {
            if (matches.length == 0 || visiblePageIndex == 0) {
                $('#' + settings.uid + '-prev').css('visibility', 'hidden');
            }
            else {
                $('#' + settings.uid + '-prev').css('visibility', 'visible');
            }
            if (matches.length == 0 || visiblePageIndex == matches.length - 1) {
                $('#' + settings.uid + '-next').css('visibility', 'hidden');
            }
            else {
                $('#' + settings.uid + '-next').css('visibility', 'visible');
            }
        }

        function _generateUid() {
            var uid = 'pager';
            for (var i = 0; i < 8; i++) {
                uid += Math.floor(Math.random() * 10);
            }
            return uid;
        }

        function _prevClicked() {
            if (visiblePageIndex > 0) {
                _swapPages(visiblePageIndex - 1);
            }
            return false;
        }

        function _nextClicked() {
            if (visiblePageIndex < matches.length - 1) {
                _swapPages(visiblePageIndex + 1);
            }
            return false;
        }

        function _swapPages(showIndex) {
            if (showIndex < 0 || showIndex >= matches.length || showIndex == visiblePageIndex || _swappingPages)
                return;

            _swappingPages = true;
            $('.content-menu a').removeClass('highlight');
            $('.content-menu li:eq(' + showIndex + ') a').addClass('highlight');
            slider.stop();
            slider.animate({ left: -((pageWidth + settings.pageOffset) * showIndex) + 'px' }, { duration: 1000 });
            visiblePageIndex = showIndex;
            _showHidePagerLinks();
            _swappingPages = false;
        }

        _initialize(this);
        return this;
    }
})(jQuery);
