/**
 * Pagination generation
 *
 * This program is used to generate pagination dynamically
 *
 * NOTICE:Vars should not be changed out of this program!
 *
 * @version 0.1.1JS
 */

Pagination.prototype.selfName = '';
Pagination.prototype.url = '';
Pagination.prototype.page = 1;
Pagination.prototype.maxPage = 1;
Pagination.prototype.lang = null;
Pagination.prototype.configDefault = null;
Pagination.prototype.config = null;
Pagination.prototype.reverse = true;
Pagination.prototype.pageStart = null; //Page list start number
Pagination.prototype.pageEnd = null; //Page list end number
Pagination.prototype.cache = null;

/**
 * Pagination Object Constructor
 * 
 * @param String selfName Variable name of the object,for example,var pg = new Pagination('pg',...)
 * @param {Object} cnf Config object
 * @param String url Url
 * @param Integer page Current page
 * @param Integer maxPage Max page
 * @param Boolean reverse If reverse pagination or not
 * @param {Object} lang Language object
 */
function Pagination(cnf, url, page, maxPage, reverse, lang) {
	if(typeof(window.jsPagination) == 'undefined') window.jsPagination = [];
	var t = window.jsPagination.length;
	window.jsPagination[t] = this;
	this.selfName = 'window.jsPagination['+t+']';
	this.url = url;
	this.maxPage = (maxPage > 0) ? maxPage : 1;
	this.reverse = reverse;
	this.page = this.getRealPage(page, this.maxPage);
	this.lang = {
		'First': 'First',
		'PreviousSection': '&lt;&lt;',
		'Previous': 'Previous',
		'Next': 'Next',
		'NextSection': '&gt;&gt;',
		'Last': 'Last'
	};
	this.cache = {
		'F': null,
		'L': null,
		'P': null,
		'N': null
	};
	this.setLang(lang);
	
	this.configDefault = {
		'matchs': '#F##P##PS##SPL##I##SPR##NS##N##L#',
		'sectionLength': 11,
		'paginationId': 'pagination',
		'itemSpliter': '',
		'suspensionPoints': '<a class="suspensionPoints">...</a>',
		'matchItem': '<a class="normalPage" href="' + this.url + '">#NOS#</a>',
		'matchCurrent': '<a class="currentPage">#NOS#</a>',
		'matchFirst': '<a class="firstPage" href="' + this.url + '">' + this.lang.First + '</a>',
		'matchFirst2': '<a class="firstPage current">' + this.lang.First + '</a>',
		'matchPreviousSection': '<a class="previousSectionPage" href="javascript:;" #ONCLICK#>' + this.lang.PreviousSection + '</a>',
		'matchPreviousSection2': '<a class="previousSectionPage current">' + this.lang.PreviousSection + '</a>',
		'matchPrevious': '<a class="previousPage" href="' + this.url + '">' + this.lang.Previous + '</a>',
		'matchPrevious2': '<a class="previousPage current">' + this.lang.Previous + '</a>',
		'matchNext': '<a class="nextPage" href="' + this.url + '">' + this.lang.Next + '</a>',
		'matchNext2': '<a class="nextPage current">' + this.lang.Next + '</a>',
		'matchNextSection': '<a class="nextSectionPage" href="javascript:;" #ONCLICK#>' + this.lang.NextSection + '</a>',
		'matchNextSection2': '<a class="nextSectionPage current">' + this.lang.NextSection + '</a>',
		'matchLast': '<a class="lastPage" href="' + this.url + '">' + this.lang.Last + '</a>',
		'matchLast2': '<a class="lastPage current">' + this.lang.Last + '</a>'
	};
	
	if (this.config == null) {
		this.config = this.configDefault;
	}
	if (typeof(cnf) == 'object' && cnf != null) {
		for (var i in cnf) {
			if (typeof(this.config[i]) != 'undefined') 
				this.config[i] = cnf[i];
		}
	}
}
/**
 * Set language for paginagion
 *
 * @param {Object} lang
 */
Pagination.prototype.setLang = function (lang)
{
	for (var i in lang) {
		if (typeof(this.lang[i]) != 'undefined') 
			this.lang[i] = lang[i];
	}
}

/**
 * Get real page number of a page
 *
 * @param Integer page
 * @param Integer max
 */
Pagination.prototype.getRealPage = function (page, max)
{
	if(this.reverse)
		return max + 1 - page;
	else
		return page;
}


/**
 * Show pagination in block #pagination or other depends on config
 *
 * @param Integer page
 */
Pagination.prototype.show = function (pageno)
{
	var page;
	if(typeof(pageno) == 'undefined') page = this.page;
	else page = this.getRealPage(pageno, this.maxPage);
	
	//Copy vars for convenience
	var config = this.config; //Configurations
	var m = this.config.matchs; //Matchs for search
	var p = this.config.matchs; //Matchs for replace
	var t = ''; //Temporary var for replace
	var StartAndEnd = false; //Flag which indicates whether Page start number and end number has been calculated
	var t_match = '';
	
	//For element list: 1 2 3 4 5
	if (config.matchItem != null && m.search(/#I#/) > -1) {
		var itemsArray = new Array();
		
		StartAndEnd = this.calculateStartAndEnd(page, this.maxPage, config);

		var j = 0;
		for (var i = this.pageStart; i <= this.pageEnd; i++) {
			t_match = '';
			if (config.matchCurrent != null && ((i == this.page))) {
				t_match = config.matchCurrent;
			}
			else {
				t_match = config.matchItem;
			}
			
			var nos = i;
			if (config.nosFunction != null) {
				eval('nos = ' + config.nosFunction + '(' + i + ');');
			}
			
			t_match = t_match.replace(/#NO#/, this.getRealPage(i, this.maxPage));
			t_match = t_match.replace(/#NOS#/, nos);
			itemsArray[j] = t_match;
			j++;
		}
		t = itemsArray.join(config.itemSpliter);
		p = p.replace(/#I#/, t);
	}
	
	//For first page
	if (config.matchFirst != null && m.search(/#F#/) > -1) {
		t_match = '';
		if (page == this.page || this.cache.F == null) {
			if (1 == this.page && config.matchFirst2 != null) {
				t_match = config.matchFirst2;
			}
			else {
				t_match = config.matchFirst;
			}
			
			var i = this.getRealPage(1, this.maxPage);
			var nos = i;
			if (config.nosFunction != null) {
				eval('nos = ' + config.nosFunction + '(' + i + ');');
			}
			
			t_match = t_match.replace(/#NO#/, i);
			t_match = t_match.replace(/#NOS#/, nos);
			this.cache.F = t_match;
		}
		else {
			t_match = this.cache.F;
		}
		p = p.replace(/#F#/, t_match);
	}
	
	//For last page
	if (config.matchLast != null && m.search(/#L#/) > -1) {
		t_match = '';
		if (page == this.page || this.cache.L == null) {
			if (this.maxPage == this.page && config.matchLast2 != null) {
				t_match = config.matchLast2;
			}
			else {
				t_match = config.matchLast;
			}
			
			var i = this.getRealPage(this.maxPage, this.maxPage);
			var nos = i;
			if (config.nosFunction != null) {
				eval('nos = ' + config.nosFunction + '(' + i + ');');
			}
			
			t_match = t_match.replace(/#NO#/, i);
			t_match = t_match.replace(/#NOS#/, nos);
			this.cache.L = t_match;
		}
		else {
			t_match = this.cache.L;
		}
		p = p.replace(/#L#/, t_match);
	}
	
	//For previous page
	if (config.matchPrevious != null && m.search(/#P#/) > -1) {
		t_match = '';
		if (page == this.page || this.cache.P == null) {
			var previousPage = this.page - 1;
			
			if (1 > previousPage && config.matchPrevious2 != null) {
				t_match = config.matchPrevious2;
			}
			else {
				t_match = config.matchPrevious;
			}
			
			var i = this.getRealPage(previousPage, this.maxPage);
			var nos = i;
			if (config.nosFunction != null) {
				eval('nos = ' + config.nosFunction + '(' + i + ');');
			}
			
			t_match = t_match.replace(/#NO#/, i);
			t_match = t_match.replace(/#NOS#/, nos);
			this.cache.P = t_match;
		}
		else {
			t_match = this.cache.P;
		}
		p = p.replace(/#P#/, t_match);
	}
	
	//For Next page
	if (config.matchNext != null && m.search(/#N#/) > -1) {
		t_match = '';
		if (page == this.page || this.cache.N == null) {
			var nextPage = this.page + 1;
			
			if (this.maxPage < nextPage && config.matchNext2 != null) {
				t_match = config.matchNext2;
			}
			else {
				t_match = config.matchNext;
			}
			
			var i = this.getRealPage(nextPage, this.maxPage);
			var nos = i;
			if (config.nosFunction != null) {
				eval('nos = ' + config.nosFunction + '(' + i + ');');
			}
			
			t_match = t_match.replace(/#NO#/, i);
			t_match = t_match.replace(/#NOS#/, nos);
			this.cache.N = t_match;
		}
		else {
			t_match = this.cache.N;
		}
		p = p.replace(/#N#/, t_match);
	}
	
	//For Next section
	if (config.matchNextSection != null && m.search(/#NS#/) > -1) {
		t_match = '';
		var nextSectionPage = page + config.sectionLength;
		if ((this.maxPage + 1) < nextSectionPage) 
			nextSectionPage = this.maxPage;
		
		if (StartAndEnd === false) {
			StartAndEnd = this.calculateStartAndEnd(page, this.maxPage, config);
		}
		
		if (this.maxPage == this.pageEnd && config.matchNextSection2 != null) {
			t_match = config.matchNextSection2;
		}
		else {
			t_match = config.matchNextSection;
		}

		var i = this.getRealPage(nextSectionPage, this.maxPage);
		var nos = i;
		if (config.nosFunction != null) {
			eval('nos = ' + config.nosFunction + '(' + i + ');');
		}
		
		t_match = t_match.replace(/#ONCLICK#/, "onclick=\"javascript:"+this.selfName+".show(" + i + ");\"");
		t_match = t_match.replace(/#NO#/, i);
		t_match = t_match.replace(/#NOS#/, nos);
		
		p = p.replace(/#NS#/, t_match);
	}
	
	//For Previous section
	if (config.matchPreviousSection != null && m.search(/#PS#/) > -1) {
		t_match = '';
		var previousSectionPage = page - config.sectionLength;
		if (0 > previousSectionPage) 
			previousSectionPage = 1;
		
		if (StartAndEnd === false) {
			StartAndEnd = this.calculateStartAndEnd(page, this.maxPage, config);
		}
		
		if (1 == this.pageStart && config.matchPreviousSection2 != null) {
			t_match = config.matchPreviousSection2;
		}
		else {
			t_match = config.matchPreviousSection;
		}
		
		var i = this.getRealPage(previousSectionPage, this.maxPage);
		var nos = i;
		if (config.nosFunction != null) {
			eval('nos = ' + config.nosFunction + '(' + i + ');');
		}
		
		t_match = t_match.replace(/#ONCLICK#/, "onclick=\"javascript:"+this.selfName+".show(" + i + ");\"");
		t_match = t_match.replace(/#NO#/, i);
		t_match = t_match.replace(/#NOS#/, nos);
		
		p = p.replace(/#PS#/, t_match);
	}
	
	//For left suspension points
	if (m.search(/#SPL#/) > -1) {
		t_match = config.suspensionPoints;
		if (StartAndEnd === false) {
			StartAndEnd = this.calculateStartAndEnd(page, this.maxPage, config);
		}
		
		if (1 == this.pageStart) {
			t_match = '';
		}
		p = p.replace(/#SPL#/, t_match);
	}
	
	//For right suspension points
	if (m.search(/#SPR#/) > -1) {
		t_match = config.suspensionPoints;
		
		if (StartAndEnd === false) {
			StartAndEnd = this.calculateStartAndEnd(page, this.maxPage, config);
		}
		
		if (this.maxPage == this.pageEnd) {
			t_match = '';
		}
		p = p.replace(/#SPR#/, t_match);
	}
	
	if (this.config.paginationId.substr(0,1) != '@') {
		var paginationDiv = document.getElementById(this.config.paginationId);
		paginationDiv.innerHTML = p;
	} else {
		var name = this.config.paginationId.substr(1);
		if (typeof($) != undefined) {
			$('[name="' + name + '"]').html(p);
		} else {
			var paginationDiv = document.getElementsByName(name);
			if (paginationDiv.length > 0) {
				for (var i = 0; i < paginationDiv.length; i++) {
					paginationDiv[i].innerHTML = p;
				}
			}
		}
	}
	
	return;
}

/**
 * Calculate page list start number and end number
 *
 * @param Integer page
 * @param Integer maxPage
 * @param {Object} conf
 */
Pagination.prototype.calculateStartAndEnd = function(page, maxPage, config)
{
	var PageStart = parseInt(page - config.sectionLength / 2 + 1);
	if (PageStart <= 0) {
		PageStart = 1;
	}
	var PageEnd = maxPage < (PageStart + config.sectionLength) ? maxPage : (PageStart + config.sectionLength - 1);
	if (PageEnd < 1) {
		PageEnd = 1;
	}
	while (PageEnd - PageStart < config.sectionLength - 1 && PageStart != 1) {
		PageStart--;
	}
	
	while (PageEnd - PageStart < config.sectionLength - 1 && PageEnd != maxPage) {
		PageEnd++;
	}
	
	this.pageStart = PageStart;
	this.pageEnd = PageEnd;
	return true;
}
