$.fn.ajaxPagination = function(options) {
	var options = $.extend({}, $.fn.ajaxPagination.defaults, options);
	var $this = $(this);
	options.pageinfo = options.book;
	options.divId = $this.attr('id');
	options.paginateIds = [];
	if(options.paginateTop != ''){
		options.paginateIds.push(options.paginateTop);
	}
	if(options.paginateBottom != ''){
		options.paginateIds.push(options.paginateBottom);
	}
	//NOTE: this.paginateInfo stores references to various components of each pagination DIV defined for this pageinstance
	//NOTE: Eg: divs[0] = 1st paginate div, pagelinks[0][0] = 1st page link within 1st paginate DIV, prevlink[0] = previous link within paginate DIV etc
	options.paginateInfo = {divs:[], pagelinks:[[]], prevlink:[], nextlink:[], previouspage:null, previousrange:[null,null], leftellipse:[], rightellipse:[]};
	options.dopagerange = false;
	options.pagerangestyle = '';
	options.ellipse = '<span style="display:none;">'+options.separator+'</span>'; //construct HTML for ellipse
	$.fn.ajaxPagination.defaults = options;
	var initialpage = $.fn.ajaxPagination.getInitialPage(options.pageinfo);
	$.fn.ajaxPagination.prototype.buildpagination(initialpage);
	$.fn.ajaxPagination.prototype.selectpage(initialpage);
};

$.fn.ajaxPagination.connect = function(options, pageurl){
	var page_request = false;
	var bustcacheparameter = "";
	$('#'+options.divId).html(options.loadStatusText);
	if(options.ajaxBustCache){ //if bust caching of external page
		bustcacheparameter = (pageurl.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()
	}
	$.ajax({
		 url: pageurl+bustcacheparameter
		,method: 'POST'
		,async: true
		,data: {
			 thumb: options.thumb
			,showPics: options.showPics
		}
		,complete: function(response){
			$('#'+options.divId).html(response.responseText);
			if(options.highslide){
				$('a.highslide').each(function() {
					this.onclick = function() {
						return hs.expand(this, options.highslideOptions);
					};
				});
				
			}
		}
	});
}

$.fn.ajaxPagination.getCookie = function(Name){ 
	var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
	if (document.cookie.match(re)) //if cookie found
		return document.cookie.match(re)[0].split("=")[1] //return its value
	return null
}

$.fn.ajaxPagination.setCookie = function(name, value){
	document.cookie = name+"="+value
}

$.fn.ajaxPagination.getInitialPage = function(pageinfo){
	var divId = $.fn.ajaxPagination.defaults.divId;
	var persistedpage = $.fn.ajaxPagination.getCookie(divId);
	var selectedpage = (this.paginatePersist && $.fn.ajaxPagination.getCookie(divId) != null) ? parseInt($.fn.ajaxPagination.getCookie(divId)) : pageinfo.selectedpage;
	return (selectedpage > pageinfo.pages.length - 1) ? 0 : selectedpage; //check that selectedpage isn't out of range
}

$.fn.ajaxPagination.prototype = {
	buildpagination: function(selectedpage){ //build pagination links based on length of this.pageinfo.pages[]
		var options = $.extend({}, $.fn.ajaxPagination.defaults, options);
		this.dopagerange = (options.pageinfo.pages.length > options.pageRange); //Bool: enable limitpagerange if pagerange value is less than total pages available
		this.pagerangestyle = this.dopagerange ? 'style="display: none;"' : ''; //if limitpagerange enabled, hide pagination links when building them
		this.showNumbersStyle = !options.showNumbers ? 'style="display: none;"' : '';
		options.paginateInfo.previousrange = null; //Set previousrange[start, finish] to null to start
		if (options.pageinfo.pages.length <= 1){ //no 0 or just 1 page
			document.getElementById(options.paginateIds[0]).innerHTML = (options.pageinfo.pages.length == 1) ? options.onePageText : "";
			return;
		}else{
			var paginateHTML = '<div class="pagination"><ul>\n';
			paginateHTML += '<li><a href="#" onclick="return false;" rel="'+(selectedpage-1)+'">&laquo; anterior</a></li>\n'; //previous link HTML
			for (var i = 0; i < options.pageinfo.pages.length; i++){
				var ellipses = {left: (i == 0 ? '&nbsp;'+options.ellipse : ''), right: (i == options.pageinfo.pages.length - 1 ? options.ellipse+'&nbsp;' : '')};
				paginateHTML += '<li '+this.showNumbersStyle+'>'+ellipses.right+'<a href="#'+(i+1)+'" onclick="return false;" rel="'+i+'" '+this.pagerangestyle+'>'+(i+1)+'</a>'+ellipses.left+'</li>\n';
			}
			paginateHTML += '<li><a href="#" onclick="return false;" rel="'+(selectedpage+1)+'">siguiente &raquo;</a></li>\n'; //next link HTML
			paginateHTML += '</ul></div>';
		}
		options.paginateInfo.previouspage = selectedpage; //remember last viewed page
		for (var i = 0; i < options.paginateIds.length; i++){ //loop through # of pagination DIVs specified
			var paginatediv = document.getElementById(options.paginateIds[i]); //reference pagination DIV
			options.paginateInfo.divs[i] = paginatediv; //store ref to this paginate DIV
			paginatediv.innerHTML = paginateHTML;
			var paginatelinks = paginatediv.getElementsByTagName("a");
			var ellipsespans = paginatediv.getElementsByTagName("span");
			options.paginateInfo.prevlink[i] = paginatelinks[0];
			if (paginatelinks.length > 0)
				options.paginateInfo.nextlink[i] = paginatelinks[paginatelinks.length - 1];
			options.paginateInfo.leftellipse[i] = ellipsespans[0];
			options.paginateInfo.rightellipse[i] = ellipsespans[1];
			options.paginateInfo.pagelinks[i] = []; //array to store the page links of pagination DIV
			for (var p = 1; p < paginatelinks.length - 1; p++){
				options.paginateInfo.pagelinks[i][p - 1] = paginatelinks[p];
			}
			var pageinstance = this;
			paginatediv.onclick = function(e){
				var targetobj = window.event ? window.event.srcElement : e.target;
				if (targetobj.tagName == "A" && targetobj.getAttribute("rel") != ""){
					if (!/disabled/i.test(targetobj.className)){ //if this pagination link isn't disabled (CSS classname "disabled")
						pageinstance.selectpage(parseInt(targetobj.getAttribute("rel")));
					}
				}
				return false
			}
		}
	},
	selectpage: function(selectedpage){
		var options = $.extend({}, $.fn.ajaxPagination.defaults, options);
		//replace URL's root domain with dynamic root domain (with or without "www"), for ajax security sake:
		if (options.pageinfo.pages.length > 0){
			var ajaxfriendlyurl = options.pageinfo.pages[selectedpage].replace(/^http:\/\/[^\/]+\//i, "http://"+window.location.hostname+"/");
			$.fn.ajaxPagination.connect(options, ajaxfriendlyurl);
		}
		if (options.pageinfo.pages.length <= 1){ //if this book only contains only 1 page (or 0)
			return;
		}
		var paginateInfo = options.paginateInfo
		for (var i = 0; i < paginateInfo.divs.length; i++){ //loop through # of pagination DIVs specified
			paginateInfo.prevlink[i].className = (selectedpage == 0) ? "prevnext disabled" : "prevnext"; //if current page is 1st page, disable "prev" button
			paginateInfo.prevlink[i].setAttribute("rel", selectedpage - 1); //update rel attr of "prev" button with page # to go to when clicked on
			paginateInfo.nextlink[i].className = (selectedpage == options.pageinfo.pages.length - 1) ? "prevnext disabled" : "prevnext";
			paginateInfo.nextlink[i].setAttribute("rel", selectedpage + 1);
			paginateInfo.pagelinks[i][paginateInfo.previouspage].className = ""; //deselect last clicked on pagination link (previous)
			paginateInfo.pagelinks[i][selectedpage].className = "currentpage"; //select current pagination link
		}
		paginateInfo.previouspage = selectedpage; //Update last viewed page info
		$.fn.ajaxPagination.setCookie(options.divId, selectedpage);
		this.limitpagerange(selectedpage); //limit range of page links displayed (if applicable)
	},
	limitpagerange: function(selectedpage){
		var options = $.extend({}, $.fn.ajaxPagination.defaults, options);
		//reminder: selectedpage count starts at 0 (0=1st page)
		var paginateInfo = options.paginateInfo;
		if (this.dopagerange){
			var visiblelinks = options.pageRange - 1; //# of visible page links other than currently selected link
			var visibleleftlinks = Math.floor(visiblelinks / 2); //calculate # of visible links to the left of the selected page
			var visiblerightlinks = visibleleftlinks + (visiblelinks % 2 == 1 ? 1 : 0); //calculate # of visible links to the right of the selected page
			if (selectedpage < visibleleftlinks){ //if not enough room to the left to accomodate all visible left links
				var overage = visibleleftlinks - selectedpage;
				visibleleftlinks -= overage; //remove overage links from visible left links
				visiblerightlinks += overage; //add overage links to the visible right links
			}else if((options.pageinfo.pages.length-selectedpage - 1) < visiblerightlinks){ //else if not enough room to the left to accomodate all visible right links
				var overage = visiblerightlinks - (options.pageinfo.pages.length-selectedpage - 1);
				visiblerightlinks -= overage; //remove overage links from visible right links
				visibleleftlinks += overage; //add overage links to the visible left links
			}
			var currentrange = [selectedpage - visibleleftlinks, selectedpage + visiblerightlinks] //calculate indices of visible pages to show: [startindex, endindex]
			var previousrange = paginateInfo.previousrange //retrieve previous page range
			for (var i=0; i<paginateInfo.divs.length; i++){ //loop through paginate divs
				if (previousrange){ //if previous range is available (not null)
					for (var p = previousrange[0]; p <= previousrange[1]; p++){ //hide all page links
						paginateInfo.pagelinks[i][p].style.display = "none";
					}
				}
				for (var p = currentrange[0]; p <= currentrange[1]; p++){ //reveal all active page links
					paginateInfo.pagelinks[i][p].style.display = "inline";
				}
				paginateInfo.pagelinks[i][0].style.display = "inline"; //always show 1st page link
				paginateInfo.pagelinks[i][options.pageinfo.pages.length - 1].style.display = "inline"; //always show last page link
				paginateInfo.leftellipse[i].style.display = (currentrange[0]>1) ? "inline" : "none"; //if starting page is page3 or higher, show ellipse to page1
				paginateInfo.rightellipse[i].style.display = (currentrange[1] < options.pageinfo.pages.length - 2) ? "inline" : "none"; //if end page is 2 pages before last page or less, show ellipse to last page
			}
		}
		paginateInfo.previousrange = currentrange
	},
	refresh: function(pageinfo){
		var options = $.extend({}, $.fn.ajaxPagination.defaults, options);
		$.fn.ajaxPagination.defaults.pageinfo = pageinfo;
		var initialpage = $.fn.ajaxPagination.getInitialPage(pageinfo);
		this.buildpagination(initialpage);
		this.selectpage(initialpage);
	}
}
