/**
 * $Workfile: atCommon.js $
 * $Revision: 7 $
 *  $Modtime: 12/05/09 13:55 $
 *   $Author: Peter.goulborn $ 
 * 
 * Class: Astun.Common
 * Container for commonly needed classes and functions common to many situations
 */
if (!Prototype) throw new Error('Prototype library not found');  // Needs to be nicer, possibly iSharemaps-wide library error?

if (!Astun) var Astun = {};
if (!Astun.JS) Astun.JS = {};
if (!Astun.JS.Common) Astun.JS.Common = {};
/* Functions */

Astun.JS.Common.addStylesheet = function(href) {
//writes in CSS stylesheet that will only be available for JS-enabled browsers
	var jsStylesheet = new Element('link', {'rel': 'stylesheet', 'type': 'text/css', 'href': href});
	$$('head')[0].insert(jsStylesheet);
	jsStylesheet.insert({'after':'\n'});
}

Astun.JS.Common.enterKey = function(e, elementName) {
	var evt = e || window.event;
	evt = Event.extend(evt);
	var keynum = evt.keyCode || evt.which;
	if (keynum == 13) { //drop out and allow default action
		$(elementName).click();
		Event.stop(evt);
		return false;
	}
	return true;
}


/* Classes */
Astun.JS.Common.QueryHandler = Class.create(
{
/**
     * Constructor: Astun.JS.Common.QueryHandler
     * Create a new handler for the page's URL query string.
     * This handler is case-insensitive with respect to parameter names, 
     * e.g. foo=bar and FOO=bar are the same.  It does not touch the case of
     * the parameter values.  
     * 
     * Parameters
     * ----------
     * aliases - { object } pairs of parameter names with CSV list of aliases.
     *			 E.g.: {'myparam': 'mp, myparameter'}.  There is no need to 
     *           supply alternatives for different case variants.  The 'key'
     *           will be the name that will be made available by the object.
     * 
     * Returns
     * -------
     * { boolean } - true if valid parameters were found in the URL, 
     *               false otherwise.
     */
	'initialize': function( aliases ) {
		var pageparameters = window.location.search.toQueryParams();
		var paramKeys = Object.keys(pageparameters);
		this.aliases = {};
		this.cases = {};
		this.cases.array = [];
		this.cases.nameIndex = {};
		this.cases.matched = false;
		
		if (aliases && aliases instanceof Object && aliases.constructor === Object) {
			// only parse aliases if a 'proper' object.
			for (var PARAM in aliases) {
				//create lookup object keyed by aliases rather than desired parameter name.
				if (aliases.hasOwnProperty(PARAM)) {
					var param = PARAM.toLowerCase()
					var aliaslist = aliases[PARAM].toLowerCase().split(',');
					while (aliaslist.length) {
						this.aliases[aliaslist.pop().strip()] = param;					
					}
				}
			}
		}

		var parameters = {};	
		
		
		for (var k = 0 ; k < paramKeys.length; k++) {
			var KEY = paramKeys[k];
			var key = KEY.toLowerCase();
			
			if (key in this.aliases) {
				key = this.aliases[key];  // always store values under desired name rather than alias.
			}
			
			// Store value, if multiple parameters of equivalent names then store values in an array.
			if (key in parameters) {
				if (!Object.isArray(parameters[key])) parameters[key] = [parameters[key]];
					parameters[key].push(pageparameters[KEY]);
				}
			else {
				var keyval = pageparameters[KEY];
				parameters[key] = ( keyval === undefined ) ? '' : keyval;
			}
		}
		
		this.parameters = parameters;
	},
	
	'getParameter': function( name ) {
		/**
		 * Function: getParameter
		 * Returns the value for a parameter in the querystring.  
		 * This will be a string, if one value found, an array of strings if
		 * many values found and undefined if the parameter is not found. 
		 * This will return the value found for any aliases specified when
		 * the object was created.  Aliases cannot be used here to find the
		 * value.
		 *
		 * Parameters:
		 * name - { string } name of a parameter.
		 *
		 * Returns: { string } || { array } of { string } || undefined
		 * 
		 */
		return this.parameters[name.toLowerCase()];
	},
	
	'addCase': function( name, parameterList, callback) {
		/**
		 * Function: addCase
		 * Returns the value for a parameter in the querystring.  
		 * This will be a string, if one value found, an array of strings if
		 * many values found and undefined if the parameter is not found. 
		 * This will return the value found for any aliases specified when
		 * the object was created.  Aliases cannot be used here to find the
		 * value.
		 *
		 * As this method can only be called after the querystring has already
		 * been processed, it can immediately determine whether the case is 
		 * valid or not.  Invalid cases are ignored.
		 *
		 * Parameters:
		 * name - { string } name for the case.
		 * parameters - { string } comma separated list of parameter names.
		 * callback - { function } function to be called if parameters are
		 *            present in querystring.  Function is assumed to take
		 *            object of { parameter : value } pairs as argument.
		 *
		 * Returns: { boolean } - true if case is valid, false if not.
		 * 
		 */
		 var paramArray = parameterList.toLowerCase().split(',');
		 var parameters = {};
		 
		 for (var p = 0; p < paramArray.length; p++) {
			var parameter = paramArray[p].strip();
			if (! (parameter in this.parameters)) {
				return false; // parameter has not matched so exit function
			}
			parameters[parameter] = this.parameters[parameter];
		 }
		 
		 this.cases.nameIndex[name] = this.cases.array[this.cases.array.push( { 'name': name, 'parameters': parameters, 'callback': callback } ) - 1];
		 this.cases.matched = true;
		 
		 return true;
		 
		 
	},
	
	'processLastCase': function( ) {
		
		/**
		 * Function: processLastCase
		 * Executes callback function for last added matching case.
		 * 
		 *
		 * Parameters:
		 * none
		 *
		 * Returns: return value of case's callback function.
		 * 
		 */
		 var caseObject = this.cases.array[this.cases.array.length - 1];
		 return caseObject.callback(caseObject.parameters);
	},
	
	'processFirstCase': function( ) {
		
		/**
		 * Function: processFirstCase
		 * Executes callback function for first added matching case.
		 * 
		 *
		 * Parameters:
		 * none
		 *
		 * Returns: return value of case's callback function.
		 * 
		 */
		 var caseObject = this.cases.array[0];
		 return caseObject.callback(caseObject.parameters);
	},
	
	'processCase': function( name ) {
		
		/**
		 * Function: processFirstCase
		 * Executes callback function for first added matching case.
		 * 
		 *
		 * Parameters:
		 * name - { string } name of case to process.
		 *
		 * Returns: return value of case's callback function or { boolean }
		 *          false if case not found.
		 * 
		 */
		 if ( !(name in this.cases.nameIndex) ) {
			return false;
		 }
		 var caseObject = this.cases.nameIndex[name];
		 return caseObject.callback(caseObject.parameters);
	}
});