/**
 * @fileOverview
 * Tools for handling DAAPI discovery.
 * The Nyx main library MUST be loaded before this script.
 * 
 * @author Glen Ford (glenford [at] yahoo.com)
 * @namespace NYX
 */

/**
 * @class
 * Takes a template and a DAAPI discovery result, and writes its GUI.
 * 
 * @param {String} idRoot			root of the ID pattern that ties this object's DOM elements together
 * @param {String} itemTemplate		template wtih @-delimited variables; the GUI for each discovered item is based on this template
 */
NYX.DiscoWriter = function(idRoot, itemTemplate) {
	//do some inheritance
	NYX.util.obj.extend(this, NYX.TemplateTool);
	
	//required, but don't necessarily have to be set in the constructor call
	this.idRoot = idRoot;
	if (typeof itemTemplate == "string") this.template = itemTemplate;
	else this.template = "@Nyx.PageTitle@";
	
	/**
	 * Maximum number of items to present; defaults to show all
	 * @type {int}
	 */
	this.discoLimit = 99;
	
	/**
	 * Text to show as a page title if there isn't one in the discovered item;
	 * this prevents errors on a corner case.
	 * @type {String}
	 */
	this.untitledText = "Untitled";
	
	/**
	 * Text to use as the name of the DAAPI Section if there isn't one.
	 * Only needed if your template exposes the section.
	 * @type {String}
	 */
	this.unnamedSection = "";
	
	/**
	 * Used to separate DAAPI Category names; only needed if your template exposes the section.
	 * @type {String}
	 */
	this.categoryJoin = ", ";
	
	//internal use
	this.discoContent = [];
	
	this.prepareData = function(discoItem) {
		//cleans up a data item; override this as needed to add/subtract post-processing of the flattened data object
		
		//first, flatten 
		var dataObj = this.flattenDaapiItem(discoItem);
		
		//join the Categories into a string
		if (typeof discoItem.Categories == "object") {
			//should be safe to assume an array
			dataObj.Categories = "";
			for (var catIdx = 0; catIdx < discoItem.Categories.length; catIdx++) {
				dataObj.Categories += discoItem.Categories[catIdx].Name + this.categoryJoin;
			}
			if (catIdx > 0) {
				dataObj.Categories = dataObj.Categories.substring(0, dataObj.Categories.length - this.categoryJoin.length);
			}
		}
		
		//make sure the title isn't blank
		if (typeof dataObj.PageTitle != "undefined") {
			if ( NYX.util.string.isBlank(dataObj.PageTitle) ) dataObj.PageTitle = this.untitledText;
		}
		
		//fix null Section
		if (discoItem.Section == null) {
			dataObj.Section = this.unnamedSection;
		} else if (typeof discoItem.Section != "undefined") {
			if ( NYX.util.string.isBlank(discoItem.Section.Name) ) dataObj.Section = this.unnamedSection;
			else dataObj.Section = discoItem.Section.Name;
		}
		
		return dataObj;
	}
	
	/**
	 * Processes the discovered content and writes the GUI into the DOM.
	 * Note that while this was designed to process multiple content items, it can be 
	 * "faked out" by passing a single item wrapped in an array.
	 * @param {Array} daapiResponse    a DiscoverContentAction.DiscoveredContent array (or something with the same interface)
	 */
	this.writeGui = function(daapiResponse) {
		this.discoContent = daapiResponse;
		
		var discoData, itemIdx, loopLimit, html, targetElem;
		targetElem = this.getElem(this.DOM_TARGET_SUFFIX);
		
		this.initGui();
		loopLimit = this.discoContent.length < this.discoLimit ? this.discoContent.length : this.discoLimit;
		for (itemIdx = 0; itemIdx < loopLimit; itemIdx++) {
			//get processable data
			discoData = this.prepareData(this.discoContent[itemIdx]);
			//console.group("DiscoWriter content item " + itemIdx); console.dir(discoData); console.groupEnd();
			
			//do the template replacements for this item 
			html = this.processTemplate(discoData, this.template);
			
			//apply the alternate row classes
			html = this.applyAltClasses(itemIdx, html);
			
			//call the customizable method to do more replacements
			html = this.customizeItem(discoData, html, targetElem, itemIdx);
			
			//append the HTML to the content target
			targetElem.innerHTML += html;
		}
		
		this.finishGui();
		
		//show the content and hide the wait message/spinner
		this.showTarget(targetElem);
	}
	
	/** 
	 * An empty method your HTML page can override to do your own GUI customizations.
	 * Called before the discovery item processing begins. 
	 */
	this.initGui = function() {
		return true;
	}
	
	/** 
	 * An empty method your HTML page can override to do your own GUI customizations.
	 * Called after the discovery item processing completes.
	 */
	this.finishGui = function() {
		return true;
	}
	
	/** 
	 * An empty method your HTML page can override to do your own GUI customizations.
	 * Called once for each line-item in the discovered data. 
	 * <p><b>IMPORTANT:</b> always return the itemHtml (processed or otherwise)</p>
	 * 
	 * @param {Object}      dataObj               the "flattened" data object (contains values that replace template variables)
	 * @param {String}      itemHtml              existing HTML for the line-item's GUI
	 * @param {DOM:Element} domElemThisWritesTo   element that the GUI is written to
	 * @param {int}         itemIndex             current line-item's position in the discovered content array
	 * 
	 * @return {String} the processed HTML for this line-item
	 */
	this.customizeItem = function(dataObj, itemHtml, domElemThisWritesTo, itemIndex) {
		return itemHtml;
	}
}
