/**
 * This paginationGid javascript Object. The object make the work more easy to
 * bind the pagination and grid plugin together. Of course, you also can
 * individually use pagination plugin and grid plugin, it would be more
 * flexible!
 * 
 * @author Jack Rao
 * @param totalNum:
 *            Total Count of entries to paginate
 * @param parameters:
 *            Few parameters that pagination plugin need.
 * @return {Object} jQuery Object
 * Very impressive,page scroll function extended by Ryan Huang
 */
 
var searchPaginationGlobalData = {};


function PaginationGrid(varParameters) {
	var parameters = {
		paginationId:null,
		panelName:"",
		innerHtml:"",
		pageSize : 1,
		localeStr : "en_GB",
		queryStr : "",
		totalNumURL : "",
		paginationURL : "",
		displayFields : [],
		sortFields : [],
		tabGridTag : "",
		paginationTag : "",
		callBackHandle : null
	};

	parameters = varParameters;

	var totalNum;
	
	this.getTotalCount = function(){
		return totalNum;
	}

	this.isNull = function(obj) {
		if (typeof(obj) == "undefined") {
			return true;
		}
		if (obj == null) {
			return true;
		}
		if (obj == "") {
			return true;
		}
		var regu = "^[ ]+$";
		var re = new RegExp(regu);
		return re.test(obj);
	};

	this.checkRequestAvailable = function() {
		if (this.isNull(parameters.queryStr)
				|| this.isNull(parameters.paginationURL)
				|| this.isNull(parameters.tabGridTag)
				|| this.isNull(parameters.paginationTag)) {
			return false;
		}
		return true;
	};

	this.pageselectCallback = function(page_id) {
		$(".gridLoading").remove();
		var pannel = $(parameters.panelName);
		var panelWidth = pannel.width();
		var panelHeight = pannel.height();
		var laodingHtml = '<div class="gridLoading"><div class="gridLoadingStatus"></div></div>';
		pannel.append(laodingHtml);
		$(".gridLoading").css("width",panelWidth);
		$(".gridLoading").css("height",panelHeight);
		$(".gridLoadingStatus").css("left",panelWidth/2 - 50);
		$(".gridLoadingStatus").css("top",panelHeight/2 - 50);
		$.getJSON(parameters.paginationURL, {
					localeStr : parameters.localeStr,
					queryStr : parameters.queryStr,
					pageIndex : page_id + 1,
					pageSize : parameters.pageSize
				}, function call(data) {
					// Create pagination element
					$(".gridLoading").remove();
					$(parameters.tabGridTag).grid(data.Result, {
								panelName : parameters.panelName,
								innerHtml : parameters.innerHtml,
								display_fields : parameters.displayFields,
								sort_fields : {},
								callBackHandle:parameters.callBackHandle
							});
				});
	};

	this.getTotalNum = function() {

		if (this.checkRequestAvailable) {
			$.ajax({
						url : parameters.totalNumURL,
						async : false,
						dataType : 'json',
						data : {
							localeStr : parameters.localeStr,
							queryStr : parameters.queryStr
						},
						success : function(data) {
							totalNum = data.TotalNum;
						}
					});
		}
	};

	this.displayData = function(PageIndexNum) {

		if (this.checkRequestAvailable) {
			$.getJSON(parameters.paginationURL, {
						localeStr : parameters.localeStr,
						queryStr : parameters.queryStr,
						pageIndex : PageIndexNum,
						pageSize : parameters.pageSize
					}, function call(data) {
						// Create pagination element
						$(parameters.tabGridTag).grid(data.Result, {
									panelName : parameters.panelName,
									innerHtml : parameters.innerHtml,
									display_fields : parameters.displayFields,
									sort_fields : {},
									callBackHandle:parameters.callBackHandle
								});
					});
		}
	};

	/**
	 * This function excute paginationGrid init.
	 */
	this.init = function() {
		
		this.getTotalNum();

		$(parameters.paginationTag).pagination(totalNum, {
					page_size : parameters.pageSize,
					callback : this.pageselectCallback,
					paginationId:parameters.paginationTag
				});

		this.displayData(1);
	}
}


/**
 * This jQuery pagination plugin.
 * 
 * @author Jack Rao
 * @param totalNum:
 *            Total Count of entries to paginate
 * @param parameters:
 *            Few parameters that pagination plugin need.
 * @return {Object} jQuery Object
 */
jQuery.fn.pagination = function(totalNum, parameters) {
	parameters = jQuery.extend({
				paginationId:'',
				display_size:10,
				scroll_size:1,
				// The number of item on the per page (default is 10)
				page_size : 10,
				link_to : "javascript:void(0);",
				prev_text : "Prev",
				next_text : "Next",
				// If is tue, the prev button always display;
				// If is not true, the prev button will disappear when current
				// page is the first page.
				prev_show_always : false,
				// If is tue, the next button always display;
				// If is not true, the next button will disappear when current
				// page is the last page.
				next_show_always : false,
				callback : function() {
					return false;
				}
			}, parameters || {});

	return this.each(function() {
		/**
		 * Calculate the maximum number of pages
		 */
		function numPages() {
			return Math.ceil(totalNum / parameters.page_size);
		}
		
		function initSearchPaginationData(pagination_id){
			searchPaginationGlobalData[pagination_id] = {};
			searchPaginationGlobalData[pagination_id].startIndex = 0;
			searchPaginationGlobalData[pagination_id].currentPage = 0;
		}
		
		function getSearchPaginationData(pagination_id){
			return 	searchPaginationGlobalData[pagination_id];
	   }
	   
		/**
		 * This is the event handling function for the pagination links.
		 * 
		 * @param {int}
		 *            page_id The new page number
		 */
		function pageSelected(page_id, evt) {
			var pgData = getSearchPaginationData(parameters.paginationId);
			pgData.currentPage = page_id;
			drawLink();
			var continuePropagation = parameters.callback(page_id);
			if (!continuePropagation) {
				if(evt){
					if (evt.stopPropagation) {
						evt.stopPropagation();
					} else {
						evt.cancelBubble = true;
					}
				}
			}
			return continuePropagation;
		}

		/**
		 * This function inserts the pagination links into the container element
		 */
		function drawLink() {
			
			panel.empty();
			var maxNumPages = numPages();
			var displaySize = parameters.display_size;
			var scroll_size = parameters.scroll_size;
			var pgData = getSearchPaginationData(parameters.paginationId);
			var currentPage = pgData.currentPage;
			var startIndex = pgData.startIndex;
			var endIndex;
			if(displaySize > maxNumPages){
				displaySize = maxNumPages;
				startIndex = 0;
				endIndex = displaySize;
			}else{
				var endIndex = startIndex + displaySize >= maxNumPages ?  maxNumPages : startIndex + displaySize;
			}
			if(maxNumPages==1){
				return;
			}
			// Helper function returns a handler function that calls
			// pageSelected with the right page_id
			var getClickHandler = function(page_id) {
				return function(evt) {
					return pageSelected(page_id, evt);
				}
			}
			// Helper function for generating a single link
			var appendItem = function(page_id, appendparameters) {
				page_id = page_id < 0 ? 0 : (page_id < maxNumPages
						? page_id
						: maxNumPages - 1);
				appendparameters = jQuery.extend({
							text : page_id + 1,
							classes : ""
						}, appendparameters || {});
				if (page_id == currentPage) {

					if (appendparameters.classes) {
						var lnk = $("<span class='" + appendparameters.classes
								+ "'>" + (appendparameters.text) + "</span>");
					} else {
						var lnk = $("<span class='current'>"
								+ (appendparameters.text) + "</span>");
					}
				} else {
					var lnk = $("<a>" + (appendparameters.text) + "</a>").bind(
							"click", getClickHandler(page_id)).attr('href',
							parameters.link_to);
				}
				panel.append(lnk);
			}
			// Generate "Previous"-Link
			if (parameters.prev_text && (currentPage > 0 || parameters.prev_show_always)) {
				var lnk = $("<a>" + (parameters.prev_text) + "</a>").bind(
							"click",function(){
									if(startIndex > 0){
										pgData.startIndex = startIndex - scroll_size;
									}
									if(currentPage > 0){
										currentPage = currentPage - 1;
										pageSelected(currentPage);
									}
							}).attr('href',
							parameters.link_to);
				panel.append(lnk);
			}
			// Generate items links
			for (var i = startIndex; i < endIndex; i++) {
				appendItem(i);
			}
			// Generate "Next"-Link
			if (parameters.next_text && (currentPage < maxNumPages - 1 || parameters.next_show_always)) {
				var lnk = $("<a>" + (parameters.next_text) + "</a>").bind(
							"click",function(){
									if(startIndex + displaySize < maxNumPages){
										 	pgData.startIndex = startIndex + scroll_size;
									}
									if(currentPage < maxNumPages - 1){
											currentPage = currentPage + 1;
											pageSelected(currentPage);
									}
							}).attr('href',
							parameters.link_to);
				panel.append(lnk);
			}
		}

		// Create a sane value for totalNum and page_size
		totalNum = (!totalNum || totalNum < 0) ? 1 : totalNum;
		parameters.page_size = (!parameters.page_size || parameters.page_size < 0)
				? 1
				: parameters.page_size;

		// Store DOM element for easy access from all inner functions
		var panel = jQuery(this);

		initSearchPaginationData(parameters.paginationId);
		// When all initialisation is done, draw the links
		drawLink();
	});
}

