/*
 * Contains common functionality used in both admin and public areas
 * of the site
 *
 * DATE			DEVELOPER		COMPANY					ACTION
 * 2008-10-22	Geoff Beaumont	Creative and Brand Ltd.	Created - separated from main.js
 * 2008-11-10	Geoff Beaumont	Creative and Brand Ltd.	Moved some of the YUI extensions in here,
 *														deprecated in_array extension in favour of 
 *														YUI version.
 * 2008-11-11	Geoff Beaumont	Creative and Brand Ltd.	Moved some YUI extensions to admin_main.js - not needed 
 *														by front end, at least at the moment.
 *														Replaced in_array prototype with CaB.inArray function - 
 *														much smaller scope so more efficient. Also moved other
 *														functions under YAHOO.CaB namespace to avoid clashes.
 */

// Define the CaB namespace, where we create our own extensions
YAHOO.namespace('CaB');
var CaB = YAHOO.CaB;

// Enclose definitions in an anonymous function, to limit variable scope
(function(){
	var Dom = YAHOO.util.Dom,
		Lang = YAHOO.lang,
		Util = YAHOO.util,
		Event = Util.Event,
		//Connect = Util.Connect,
		Widget = YAHOO.widget;
	
	/**
	 * Set as a validator function for YUI elements such as table cell editors,
	 * which expect the value to be returned if valid, else null.
	 */
	CaB.inArray = function(arr, datum, strict){
		if (strict) function equals(a,b) { return a === b }
	    else function equals(a,b) { return a == b }
	
	    for (var i in arr) {
	        if (equals(arr[i], datum)) return true;
	    }
	    return false;
	};
	
	/**
	 * Converts an XML node representing an error stack into a
	 * string which can be displayed to the user.
	 *
	 * If neither displayAll nor displayAllMaxLevel are true, then
	 * only the first error message of the maximum reported error
	 * level is returned.
	 *
	 * @param	oXmlNode			DOMElement	The 'errors' node from a handler XML block
	 * @param	displayAll			string		If true, concatenate all errors together. Default false. 
	 * @param	displayAllMaxLevel	string		If true, concatenate all errors of the maximum reported 
	 *											level together. Default false. Ignored if displayAll is true.
	 * @return						string		Error message(s) as a single string
	 */
	CaB.parseErrorsXml = function(oXmlNode, displayAll, displayAllMaxLevel){
		displayAll = displayAll == true ? true : false;
		displayAllMaxLevel = displayAllMaxLevel == true ? true : false;
		
		var maxErrorLevel = parseInt(oXmlNode.getAttribute('max_error_level'));
		var errorString = '';
		
		for(var i=0; i < oXmlNode.childNodes.length; i++){
			if(displayAll || maxErrorLevel == parseInt(oXmlNode.childNodes[i].getAttribute('level'))){
				if(errorString.length > 0) errorString += '.<br/>';
				errorString += oXmlNode.childNodes[i].firstChild.nodeValue;
				if (!displayAll && !displayAllMaxLevel) break;
			}
		}
		if(errorString.length > 0) errorString += '.';
		return errorString;
	}
	
	/**
	 * Displays a message to the user. All messages should be displayed
	 * using this function, so that the alert mechanism can be changed
	 * in one place for consistency.
	 *
	 * NOTE: type and modal are currently ignored, as the mechanism is 
	 * a simple alert dialogue.
	 *
	 * @param	message	string	The text to display to the user
	 * @param	type	string	The type of message - can be used to identify message types 
	 *							eg. by colour or icon. Default 'alert'.
	 * @param	modal	boolean	If true, prevent the user doing anything else while the 
	 *							message is displayed. Default true.
	 */
	CaB.displayAlert = function(message, type, modal){
		modal = modal == false ? false : true;
		if (typeof type == 'undefined') type = 'alert';
		if(typeof type == 'number'){
			switch(maxErrorLevel){
				case DP_ERROR_LEVEL_DEPRECATED:
					type = 'deprecated';
					break;
				case DP_ERROR_LEVEL_NOTICE:
					type = 'notice';
					break;
				case DP_ERROR_LEVEL_WARNING:
					type = 'warning';
					break;
				case DP_ERROR_LEVEL_ERROR:
					type = 'error';
					break;
				default:
					type = 'alert';
			}
		}
		
		// Change code below to alter message display
		//alert(message);
		// Instantiate the Dialog
		var dia = new YAHOO.widget.SimpleDialog("dpAlert", {
			width: "330px",
			fixedcenter: true,
			visible: true,
			draggable: false,
			modal: true,
			close: false,
			text: message,
			constraintoviewport: true,
			buttons: [ { text:"Okay", handler:function(){this.hide();} }]
		});
		dia.setHeader('DECKPLANNER&trade;');
		dia.render('wrapper');
		dia.show();
	}
	
	/**
	 * Displays a question to the user, with Okay or Cancel responses
	 * - currently just displays the standard javascript confirm, but 
	 * this allows us to wrap all instances with a fancier version 
	 * if we want to.
	 * 
	 * @param	message	string	The text to display to the user
	 */
	CaB.confirm = function(message){
		return confirm(message);
	}
	
	/**
	 * Dump value to popup window, for debugging. Shows
	 * structure of object or array in a similar way to 
	 * PHP's CaB.print_r() or var_dump().
	 *
	 * Mildly modified from:
	 * http://remorse.nl/weblog/javascript_debugging_CaB.print_rvar_dump_in_javascript_like_php/
	 */
	CaB.print_r = function(element, limit, depth){
		depth = depth?depth:0;
		limit = limit?limit:1;
		var returnString = '<ol>';
		for(property in element)
		{
			//Property domConfig isn't accessable
			if (property != 'domConfig')
			{
				returnString += '<li><strong>'+ property + '</strong> <small>(' + (typeof element[property]) +')</small>';
				if (typeof element[property] == 'number' || typeof element[property] == 'boolean')
					returnString += ' : <em>' + element[property] + '</em>';
				if (typeof element[property] == 'string' && element[property])
					returnString += ': <div style="background:#C9C9C9;border:1px solid black; overflow:auto;"><code>' +
										element[property].replace(/</g, '<').replace(/>/g, '>') + '</code></div>';
				if ((typeof element[property] == 'object') && (depth <limit))
					returnString += CaB.print_r(element[property], limit, (depth + 1));
				returnString += '</li>';
			}
		}
		returnString += '</ol>';
		if(depth == 0)
		{
			winpop = window.open("", "","width=800,height=600,scrollbars,resizable");
			winpop.document.write('<pre>'+returnString+ '</pre>');
			winpop.document.close();
		}
		return returnString;
	}
	
	CaB.buildPostStringFromForm = function(form, ignoreFields){
		if(Lang.isString(form)) form = new Util.Element(form);
		if(!Lang.isArray(ignoreFields)) ignoreFields = new Array(ignoreFields);
	
		// Get all form fields
		var tmpFields = form.getElementsByTagName('input');
		var fields = new Array();
		for(var j=0; j < tmpFields.length; j++)
			if(tmpFields[j].name) fields.push(tmpFields[j]);
		tmpFields = form.getElementsByTagName('textarea');
		for(j=0; j < tmpFields.length; j++)
			if(tmpFields[j].name) fields.push(tmpFields[j]);
		tmpFields = form.getElementsByTagName('select');
		for(j=0; j < tmpFields.length; j++)
			if(tmpFields[j].name) fields.push(tmpFields[j]);
	
		// Assemble post string
		var post = '';
		var doneFields = new Array();
		for(var i=0; i < fields.length; i++){
			if(!CaB.inArray(ignoreFields,fields[i].name) && !CaB.inArray(doneFields,fields[i].name)){
				// might need to switch on tag first to avoid avoid errors with textareas and selects
				switch(fields[i].type){
					case 'checkbox':
						// We need to get all checked values
						var group = Dom.getElementsBy(function(el){return el.name == fields[i].name ? true : false;},'input',form);
						var valString = '';
						for(j=0; j < group.length; j++){
							if(group[j].checked)
								valString += (valString.length > 0 ? ',' : '') + encodeURIComponent(group[j].value);
						}
						post += (post.length > 0 ? '&' : '') + encodeURIComponent(fields[i].name) + '=' + valString;
						doneFields.push(fields[i].name);
						break;
					case 'radio':
						// We need to find the checked value
						var group = Dom.getElementsBy(function(el){return el.name == fields[i].name ? true : false;},'input',form);
						var valString = '';
						for(j=0; j < group.length; j++){
							if(group[j].checked){
								valString = encodeURIComponent(group[j].value);
								break;
							}
						}
						post += (post.length > 0 ? '&' : '') + encodeURIComponent(fields[i].name) + '=' + valString;
						doneFields.push(fields[i].name);
						break;
					
					// We don't want to automatically pass all buttons - if we need to trap
					// clicks this will have to be done using event handlers
					case 'image':
						break;
					case 'submit':
						break;
					case 'button':
						break;
					
					// Default - just grab a simple value
					default:
						post += (post.length > 0 ? '&' : '') + encodeURIComponent(fields[i].name) + '=' + encodeURIComponent(fields[i].value);
				}
			}
		}
		
		return post;
	}
	
	/**
	 * IE doesn't comply to the DOM API and uses a different property for
	 * the text content of a DOM element. Use this function to avoid messy
	 * switch code everywhere.
	 *
	 * @param DOMElement element The element to extract the textContent from
	 * @return string
	 */
	CaB.xmlTextContent = function(element){
		var data = element.textContent ? element.textContent : element.text ? element.text : null;
		return data;
	}
})();