/**
 * @fileOverview
 * Objects for navigating among pages on any paginated lists; 
 * in SiteLife, these include galleries or comments.
 * 
 * @author Glen Ford (glenford [at] yahoo.com)
 * @namespace NYX
 */

NYX.Pager = function(paramBag) {
	//creates a GUI for navigation between pages on *any* paginated list (incl. DAAPI page objects)
	
	/* paramBag REQUIRED members:
	 *   .domTargetElem
	 *   .pageLength
	 *   .totalItems
	 *   .template
	 * OPTIONAL: any other property that can be set
	 */
	
	//do some inheritance
	NYX.util.obj.extend(this, NYX.TemplateTool);
	
	//CSS classes
	this.CSS_CLASS_PAGELINKS   = "paginationNavLinks"
	this.CSS_CLASS_CDTRANSPORT = "paginationTransport"
	this.CSS_CLASS_SELECT      = "paginationDropDown"
	
	//these determine whether controls are shown even when no navigation is possible
	this.alwaysShowJumpNav   = false;	//jump nav includes page links & drop down
	this.alwaysShowTransport = true;
	
	this.linkLimit = 10; //limits the number of direct-to-page links displayed (ignored if that element isn't in the template)
	
	//inherit from the paramter bag (copy properties)
	NYX.util.obj.extend(this, paramBag);
	
	//querystring variable name
	this.pageVarName = "pageNum";
	
	this.transportMaker = null;	//tool for writing CD-type transport controls; will be defaulted at run-time if needed
	this.dropDownMaker  = null;	//tool for writing drop-down control; will be defaulted at run-time if needed
	
	this.getPageCount = function() {
		var count = Math.ceil(this.totalItems / this.pageLength);
		return count;
	}
	
	//do some calculations to set current state parameters
	this.currentPage = NYX.util.querystring.get(this.pageVarName);
	if (this.currentPage == null || this.currentPage < 1) this.currentPage = 1;
	
	//action methods ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
	this.writeGui = function() {
		//clean up the link limit since it might be a string, which will cause concatenation instead of addition (thanks JavaScript!)
		this.linkLimit = Math.abs(this.linkLimit);
		
		//get the current page count
		this.pageCount = this.getPageCount();
		
		//add properties to this instance for template replacement (actual controls, etc)
		//calculate numbers for "Showing X-Y of T items" type display
		this.firstItem = (this.currentPage - 1) * this.pageLength + 1;
		this.lastItem  = this.firstItem + (this.pageLength - 1);
		if (this.lastItem > this.totalItems) this.lastItem = this.totalItems;
		
		//jump nav
		//if ( this.pageCount > 1 || this.alwaysShowJumpNav ) {
		if ( NYX.util.string.contains(this.template, "pageLinks") ) {
			this.pageLinks = this.getPageLinks();
		}
		if ( NYX.util.string.contains(this.template, "pageDropDown") ) {
			this.pageDropDown = this.getDropDownCtrl();
		}
		
		//CD-player-like controls
		if ( NYX.util.string.contains(this.template, "cdTransport") ) {
			this.cdTransport = this.getTransportCtrl();
		}
		
		//do template replacements
		this.domTargetElem.innerHTML = this.processTemplate(this, this.template);
	}
	
	this.getPageLinks = function() {
		//returns HTML of direct-to-page links
		
		//start the HTML with wrappers
		var wrapper = document.createElement("ins"); //arbitrary wrapper for collecting the HTML -- not returned
		var innerWrapper = document.createElement("span"); //for CSS classing -- *will* be returned
		innerWrapper.className = this.CSS_CLASS_PAGELINKS;
		wrapper.appendChild(innerWrapper);
		
		//calculate the range of page links to display; assume the user wants to go forward moreso that backward
		var actualLinkLimit = (this.pageCount < this.linkLimit) ? this.pageCount : this.linkLimit;
		var startPage = this.currentPage - Math.floor(this.linkLimit / 3) - 1;
		if (startPage + actualLinkLimit > this.pageCount) startPage = this.pageCount - actualLinkLimit + 1;
		if (startPage < 1) startPage = 1;
		
		//create the links
		for (var linkCount = 0; linkCount < actualLinkLimit; linkCount++) {
			var jumpNum = linkCount + startPage;
			if (jumpNum != this.currentPage) {
				var tag = document.createElement("a");
				tag.href = NYX.util.querystring.set(this.pageVarName, jumpNum);
			} else {
				var tag = document.createElement("span");
			}
			tag.innerHTML = jumpNum;
			innerWrapper.appendChild(tag);
		}
		
		return wrapper.innerHTML;
	}
	
	this.getTransportCtrl = function() {
		if ( !( this.pageCount > 1 || this.alwaysShowTransport) ) return "";
		if (this.transportMaker == null) this.transportMaker = new NYX.TextCDButtons(this);
		return this.transportMaker.getHTML();
	}
	
	this.getDropDownCtrl = function() {
		if ( !( this.pageCount > 1 || this.alwaysShowJumpNav) ) return "";
		if (this.dropDownMaker == null) this.dropDownMaker = new NYX.PageSelect(this);
		return this.dropDownMaker.getHTML();
	}
}







//child objects start here ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
NYX.TextCDButtons = function(parent) {
	//character-based "CD transport buttons" for page navigation
	this.parent = parent;
	
	/* constants for the symbols to use 
	 * -- choose carefully, as global search-and-replace may be used by child classes
	 * (recommendation: always use entities or other multi-character strings, or rare characters)
	 */
	this.SYM_FIRST = "&laquo;"  ;
	this.SYM_PREV  = "&lt;"     ;
	this.SYM_NEXT  = "&gt;"     ;
	this.SYM_LAST  = "&raquo;"  ;
	
	this.getHTML = function() {
		//wrapper to collect HTML
		var wrapper = document.createElement("ins");
		//inner wrapper for styling
		var innerWrapper = document.createElement("span"); //for CSS classing -- *will* be returned
		innerWrapper.className = this.parent.CSS_CLASS_CDTRANSPORT;
		wrapper.appendChild(innerWrapper);
		
		//link: << (first)
		if (this.parent.currentPage > 1) {
			var tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, 1);
		} else {
			var tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_FIRST;
		innerWrapper.appendChild(tag);
		
		//link: < (prev)
		if (this.parent.currentPage > 1) {
			var tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, this.parent.currentPage - 1);
		} else {
			var tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_PREV;
		innerWrapper.appendChild(tag);
		
		//link: > (next)
		if (this.parent.currentPage < this.parent.pageCount) {
			var tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, this.parent.currentPage + 1);
		} else {
			var tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_NEXT;
		innerWrapper.appendChild(tag);
		
		//link: >> (last)
		if (this.parent.currentPage < this.parent.pageCount) {
			var tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, this.parent.pageCount);
		} else {
			var tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_LAST;
		innerWrapper.appendChild(tag);
		
		return wrapper.innerHTML;
	}
}

NYX.PrevNextLinks = function(parent, paramBag) {
	//textual "CD transport buttons" for page navigation
	this.parent = parent;
	
	//constants for the text
	this.JOINER = "&nbsp;";
	this.TEXT_FIRST = "First";
	this.TEXT_PREV  = "Prev";
	this.TEXT_NEXT  = "Next";
	this.TEXT_LAST  = "Last";
	
	//param bag can override constants; also can pass in killSymbols to affect the display
	if (typeof paramBag == "object") NYX.util.obj.extend(this, paramBag);
	
	//utilize the existing class and do surgery on it
	NYX.util.obj.extend( this, new NYX.TextCDButtons(this.parent) );
	
	//override symbol constants
	if (this.killSymbols) {
		this.SYM_FIRST = this.TEXT_FIRST;
		this.SYM_PREV  = this.TEXT_PREV;
		this.SYM_NEXT  = this.TEXT_NEXT;
		this.SYM_LAST  = this.TEXT_LAST;
	} else {
		this.SYM_FIRST += this.JOINER + this.TEXT_FIRST;
		this.SYM_PREV  += this.JOINER + this.TEXT_PREV;
		this.SYM_NEXT  += this.JOINER + this.TEXT_NEXT;
		this.SYM_LAST  += this.JOINER + this.TEXT_LAST;
	}
}



NYX.PageSelect = function(parent) {
	//basic SELECT box for direct-page navigation
	this.parent = parent;
	
	//top item text
	this.DEFAULT_OPTION_TEXT = "Jump to:";
	
	this.getHTML = function() {
		//wrapper to collect HTML
		var wrapper = document.createElement("ins");
		
		var ctrl = document.createElement("select"); //for CSS classing -- *will* be returned
		ctrl.className = this.parent.CSS_CLASS_SELECT;
		
		//add the default option
		var option = document.createElement("option");
		option.innerHTML = this.DEFAULT_OPTION_TEXT;
		ctrl.appendChild(option);
		
		for (var pageIdx = 1; pageIdx <= this.parent.pageCount; pageIdx++) {
			var option = document.createElement("option");
			//option.value = pageIdx;
			option.innerHTML = pageIdx;
			ctrl.appendChild(option);
		}
		
		wrapper.appendChild(ctrl);
		
		//add the onchange event to the SELECT -- the cheap way
		var eventCode = "if (this.selectedIndex != " + this.parent.currentPage + " && this.selectedIndex > 0) " +
			"location.search = NYX.util.querystring.set(pageVarName, this.selectedIndex);" +
			"else this.selectedIndex = 0;"; 
		eventCode = eventCode.replace("pageVarName", '"' + this.parent.pageVarName + '"');
		wrapper.innerHTML = wrapper.innerHTML.replace("<select", "<select onchange='" + eventCode + "' ");
		
		return wrapper.innerHTML;
	}
}


