(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,
				fixedWidth: null,
				emergencyScrollFilter: null,
				emergencyScrollHeightOffset: null,
				emergencyScrollPadding: '1em',
				uid: _generateUid()
			}, settings);
		
		var matches = this;
		var visiblePageIndex = 0;
		var _swappingPages = false;
		var slider = this.length > 0 ? (!!settings.sliderFilter ? $(this[0]).parents(settings.sliderFilter) : $(this[0]).parent()) : null;
		var container = !!slider ? (!!settings.containerFilter ? slider.parents(settings.containerFilter) : slider.parent()) : null;
		var pageWidth = container.width();
		
		function _initialize() {
			if (matches.length <= 0)
				return;
				
			container.css({overflow: 'hidden'});
			slider.css({position: 'absolute', top: '0px', left: '0px'});
			
			for (var i = 0; i < matches.length; i++) {
				$(matches[i]).css({position: 'absolute', width: (!!settings.fixedWidth ? settings.fixedWidth : pageWidth) + 'px', left: ((pageWidth + settings.pageOffset) * i) + 'px', top: '0px'});
			}
			$(settings.insertPagingButtonsAfter || elements[elements.length - 1]).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();
			_applyEmergencyScroll();
			$(window).resize(_windowResized);
		}
		
		function _getHeight(el) {
		    var origEl = el.get(0);
		    var height = el.height();
		    var gotHidden = false;
		    el = el.parent();
		    while (el.length && el.get(0) != $('body').get(0)) {
		        if (el.css('overflow')=='hidden') {
		            height = gotHidden ? Math.min(height, el.height()) : el.height();
		            gotHidden = true;
		        }
		        el = el.parent();
		    }
		    if (!!settings.emergencyScrollHeightOffset) {
		        if (typeof(settings.emergencyScrollHeightOffset)=='function')
		        {
		            height = settings.emergencyScrollHeightOffset(origEl, height);
		        }
		    }
		    return height;
		}
		
		function _applyEmergencyScroll() {
			if (!!settings.emergencyScrollFilter) {
			    $(settings.emergencyScrollFilter, matches).each(function(){
			            $(this).css({height:_getHeight($(this)),overflow:'auto',paddingRight:(typeof(settings.emergencyScrollPadding)=='number'?settings.emergencyScrollPadding+'px':settings.emergencyScrollPadding)})
			        });
			}
		}
		
		function _removeEmergencyScroll() {
		    if (!!settings.emergencyScrollFilter) {
		        $(settings.emergencyScrollFilter, matches).css({height:'auto',overflow:'hidden'});
		    }
		}
		
		function _windowResized() {
		    _removeEmergencyScroll();
			pageWidth = container.width();
			for (var i = 0; i < matches.length; i++) {
				$(matches[i]).css({position: 'absolute', width: (!!settings.fixedWidth ? settings.fixedWidth : pageWidth) + 'px', left: ((pageWidth + settings.pageOffset) * i) + 'px', top: '0px'});
			}
			slider.stop().css({left: -((pageWidth + settings.pageOffset) * visiblePageIndex) + 'px'});
			_applyEmergencyScroll();
		}
		
		function _showHidePagerLinks() {
			if (matches.length == 0 || visiblePageIndex == 0)
			{
				$('#' + settings.uid + '-prev').hide();
			}
			else
			{
				$('#' + settings.uid + '-prev').show();
			}
			if (matches.length == 0 || visiblePageIndex == matches.length - 1)
			{
				$('#' + settings.uid + '-next').hide();
			}
			else
			{
				$('#' + settings.uid + '-next').show();
			}
		}
				
		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;
			slider.stop();
			_removeEmergencyScroll();
			$this = this;
			slider.animate({left: -((pageWidth + settings.pageOffset) * showIndex) + 'px'}, {duration: 1000, complete:_applyEmergencyScroll});
			visiblePageIndex = showIndex;
			_showHidePagerLinks();
			_swappingPages = false;
		}
		
		_initialize(this);
		return this;
	}
})(jQuery);