(function($) {

	$.fn.paginate = function(params) {
	
		// default / initial settings 
		var defaults = {
			
			itemsPerPage :		2,							//	number of items to show per page 
			currentPage :		1,							//	current page number 
			itemCount :			0,							//	total number of items to paginate
			linksToShow :		5,							//	maximum amount of numbered links to show 
			
			contentURLPrefix :	"/php/ajax/_ajaxlist_",		//	prefix for filename to load listings from 
			contentURLSuffix :	".php",						//	suffix for filename to load listings from
			countURLPrefix :	"/php/ajax/_ajaxcount_",	//	prefix for filename to load item count from 
			countURLSuffix :	".php",						//	suffix for filename to load item count from
			
			loadInitialContent:	true,						//	if true, go and fetch the first page of content (otherwise assume that the containing page has already done so)
			onPagedLoad:		null,						//	callback function fired when a page of content is loaded
			
			queryfilters:		{},							//	key:value pairs of filter parameters to pass to content-fetching / count pages
			querysort:			"",							//	comma-separated list of sort columns to pass to content-fetching pages
			
			ajaxvars:			{},							//	key:value pairs of miscellaneous vars to pass to content-fetching / count pages.
															//	Treated the same way as queryfilters except they're not written to pagination links
			
			contentContainer:	".modulecontentlist",		//	the classname of the container that the content will be loaded in to
			linksContainer:		".pagelinks"				//	the classname of the container that the numbered page links will be loaded into
		
		};
		
		var options = $.extend(defaults, params);
		
		
		
		return this.each(function() {
			
    		var $this = $(this);
			
			//	update the itemCount via AJAX if it's not been passed in.
			if (options.itemCount == 0){
			
				var countSourceURL = options.countURLPrefix + $this.attr("id") + options.countURLSuffix;
				
				$.get(countSourceURL, options.queryfilters, function(ct){
																	 
					options.itemCount = parseInt(ct);
					
					if (options.loadInitialContent){
						getInitialContent($this);
					}else{
						drawPaginationLinks($this);
						if ($.isFunction(options.onPagedLoad)) {
							options.onPagedLoad($this);
						}
					}
					
				});
				
				
			}else{
			
				if (options.loadInitialContent){
					getInitialContent($this);
				}else{
					drawPaginationLinks($this);
					if ($.isFunction(options.onPagedLoad)) {
						options.onPagedLoad($this);
					}
				}
			
			}
		
		});
		
		
		
		function drawPaginationLinks($this){
		// draw a list of pagination links 
			
			if (options.itemCount > options.itemsPerPage){
				
				var maxPageNumber = Math.ceil(options.itemCount / options.itemsPerPage);
				var linkCount = options.linksToShow - 1					// make linkCount 0-based, not 1-based.
				
				// normally start numbering at one below the current page, unless we're at page 1.
				var startPageNumber	= (options.currentPage > 1) ?  options.currentPage - 1 : options.currentPage;

				// keep listing page number links until we get to linkCount, unless we hit maxPageNumber first.
				var endPageNumber = startPageNumber + linkCount;
				endPageNumber = (endPageNumber > maxPageNumber) ? maxPageNumber : endPageNumber;
				
				// if we're close enough to the end that we're not listing enough pages, and we're far enough away from the beginning, begin numbering earlier.
				if (((endPageNumber - startPageNumber) < linkCount) && (startPageNumber > 1)){
					startPageNumber = (endPageNumber > linkCount) ? endPageNumber - linkCount : 1;
				}
				
				// create filter list for adding to numbered link hrefs
				var filterlist = "";
				$.each(options.queryfilters, function(key, val){
					if (filterlist==""){
						filterlist = key + "=" + val;
					}else{
						filterlist += "&" + key + "=" + val;
					}
				});
				
				
				
				// now create list of numbered links
				var sNumberingHTML = '';
				
				//	add "Prev" link if appropriate 
				if (options.currentPage > 1){
					sNumberingHTML += '<li><a href="#'+filterlist+'">Prev</a></li>';
				}
				for (var i = startPageNumber; i <= endPageNumber; i++){
					if (options.currentPage == i){
						sNumberingHTML += '<li class="current">'+ i +'</li>';
					}else{
						sNumberingHTML += '<li><a href="#'+filterlist+'">'+ i +'</a></li>';
					}
				}
				//	add "Next" link if appropriate 
				if (options.currentPage < maxPageNumber){
					sNumberingHTML += '<li><a href="#'+filterlist+'">Next</a></li>';
				}
				
				//	add numbered links to container UL 
				$this.find(options.linksContainer).html(sNumberingHTML);
				
				//	add event handlers to newly-added numbering links 
				$this.find('.' + options.linksContainer + ' li a').click(function(){
					getPaginationContent(this,$this);
					return false;
				});
			
			
			}else{	//(options.itemCount <= options.itemsPerPage) 	- don't show pagelinks
				$this.find(options.linksContainer).html("");
			}
					

		}
		
		
		function getInitialContent($this){
			// get the content for the first page and draw the pagination links.
			var contentSourceURL = options.contentURLPrefix + $this.attr("id") + options.contentURLSuffix;
			
			var paginationParams = {pageNumber: options.currentPage, itemsPerPage: options.itemsPerPage, sortby: options.querysort};
			var allParams = $.extend(paginationParams, options.queryfilters, options.ajaxvars);
			
			$($this).find(options.contentContainer).html('<li class="loading"></li>').load(contentSourceURL, allParams, function(){
				drawPaginationLinks($this);
				
				if ($.isFunction(options.onPagedLoad)) {
					options.onPagedLoad($this);
				}
			});
			
		}
		
		

		function getPaginationContent(pageListLink,$this){
			// get the content for the required page, draw the pagination links, and increment the current page count.
			var contentSourceURL = options.contentURLPrefix + $this.attr("id") + options.contentURLSuffix;
			var pageNumberToGet = $(pageListLink).text();
			if (!isNaN(pageNumberToGet)){
				pageNumberToGet = parseInt(pageNumberToGet);
			}else if (pageNumberToGet == "Next"){
				pageNumberToGet = options.currentPage + 1;
			}else if (pageNumberToGet == "Prev"){
				pageNumberToGet = options.currentPage - 1;
			}
			
			var paginationParams = {pageNumber: pageNumberToGet, itemsPerPage: options.itemsPerPage, sortby: options.querysort};
			var allParams = $.extend(paginationParams, options.queryfilters, options.ajaxvars);
			
			$($this).find(options.contentContainer).html('<li class="loading"></li>').load(contentSourceURL, allParams, function(){
				options.currentPage = pageNumberToGet;
				drawPaginationLinks($this);
				
				if ($.isFunction(options.onPagedLoad)) {
					options.onPagedLoad($this);
				}
				
			});
			
		}
		
		
	};

})(jQuery);
