/**
 * $Workfile: atCommon.js $
 * $Revision: 25 $
 * $Modtime: 19/10/10 11:19 $
 * $Author: Aamir.afridi $ 
 * 
 * Class: Astun.Common
 * Container for commonly needed settings, classes and functions common to many situations
 */
 
 
/********************************************************************/
/***************************** Settings *****************************/

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 = {};

/***************************** End of Settings *****************************/
/***************************************************************************/


/*********************************************************************/
/***************************** Functions *****************************/

Astun.JS.Common.addStylesheet = function(href)
{
//writes in CSS stylesheet that will only be available for JS-enabled browsers
	//ToDo: instead of href as a string, it should be an Array so that we can use addStylesheet(['a.css', 'b.css']);
	var jsStylesheet = new Element('link', {'rel': 'stylesheet', 'type': 'text/css', 'href': href});
	$$('head')[0].insert(jsStylesheet);
	jsStylesheet.insert({'after':'\n'});
}

Astun.JS.Common.trim = function( s ) {
	var	trim = s.replace( /^\s\s*/, '' ),
		whitespace = /\s/,
		i = trim.length;
	while ( whitespace.test( trim.charAt( --i) ) );
	return trim.slice( 0, i + 1 );
}

Astun.JS.Common.isArray = function( a ) {
	return Object.prototype.toString.call( a ) === "[object Array]";
}

Astun.JS.Common.isString = function( s ) {
	return Object.prototype.toString.call( s ) === "[object String]";
}

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;
}

//Public method: Create a cookie with the specified name, value and days to expire.
Astun.JS.Common.setCookie = function (c_name, value, expiredays, domain, path)
{
	if( !Astun.appType ) Astun.appType = '';
	if(Astun.appType == 'lite' || Astun.appType == 'solo') return;
	var exdate=new Date();
	exdate.setDate( exdate.getDate()+expiredays );
	var cookieOptions = $H(
		{
			'domain': domain || '',
			'path': path || '',
			'expires': ( !expiredays ) ? '' : exdate.toGMTString()		
		}
	);
	cookieOptions.toString = function(){
		var theString = '';
		this.each(function( option )
		{
			if ( option.value !== '' ) {
				theString += '; ' + option.key + '=' + option.value;
			}	
		});
		return theString;
	}
	document.cookie=c_name+ '=' +encodeURIComponent( value ) + cookieOptions.toString();
}

//Public method: Retrieve the value of the cookie with the specified name.
Astun.JS.Common.getCookie = function(sName)
{
	if( !Astun.appType ) Astun.appType = '';
	if(Astun.appType == 'lite' || Astun.appType == 'solo') return;
	// cookies are separated by semicolons
	var aCookie = document.cookie.split('; ');
	for (var i=0; i < aCookie.length; i++)
	{
		// a name/value pair (a crumb) is separated by an equal sign
		var aCrumb = aCookie[i].split('=');
		if (sName == aCrumb[0]) 
		  return (decodeURIComponent(aCrumb[1])=='') ? null : decodeURIComponent(aCrumb[1]);
	}
	// a cookie with the requested name does not exist
	return null;
}

//Convert area into radius
Astun.JS.Common.areaToRadius = function(area)
{
	return Math.sqrt(area/Math.PI);
}

//Public method: Delete all cookies that are set by astun
Astun.JS.Common.clearAstunCookies = function()
{
	//Delete the cookies that are created by astun
	var cookies = document.cookie.split(';');
	for(var i=0; i<cookies.length; i++)
	{
		var cookiename = cookies[i];
		if(cookiename.indexOf('astun:')!=-1)
		{
			Astun.JS.Common.setCookie(cookiename, '', -1 ,'', '/');
			Astun.JS.Common.setCookie(cookiename, '', -1 ,'', '');
		}
		//else debug(cookiename);
	}
}

//Public method: Prevent the arrow keys to work on specified elements.
Astun.JS.Common.stopArrowKeys = function (e)
{
	var ev = e||event;
	var key = ev.which||ev.keyCode;
	var esc = 0;
	
	switch(key){
		case 37: // left
		case 38: // up
		case 39: // right
		case 40: // down
		esc = 1;
		break;
	}
	if(esc && ev.preventDefault) ev.preventDefault();
	return esc;
}

//Public method: Prevent the arrow keys to work on specified elements.
Astun.JS.Common.stopEventProp = function (e)
{
	var ev = e||event;
	if( ev.stopPropagation ) { ev.stopPropagation(); } //For 'Good' browsers
	else { ev.cancelBubble = true; } //For IE	
}

//Public method: To maximize the window to the screen availble height and width.
Astun.JS.Common.maxWindow = function()
{
	window.moveTo(0, 0);
	if (document.all) top.window.resizeTo(screen.availWidth, screen.availHeight);
	else if (document.layers || document.getElementById) {
		if (top.window.outerHeight < screen.availHeight || top.window.outerWidth < screen.availWidth) {
			top.window.outerHeight = screen.availHeight;
			top.window.outerWidth = screen.availWidth;
		}
	}
}

//Public method: Function for debugging- no need for Astun name spacing because it will be hard to type while testing :P - Only for testing, shouldnt be present anywhere in code un-commented.
function debug(msg) { (window.console && window.console.log) ? window.console.log(msg) : alert(msg);}

/***************************** End of Functions *****************************/
/****************************************************************************/



/*******************************************************************/
/***************************** Classes *****************************/

//Check if stateManager is not available than this means that we dont need it so just return false to avoid any errors

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
		 *
		 * 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);
	}
});

/***************************** End of Classes *****************************/
/**************************************************************************/

//Overwritting window's own alert with jQuery dialog  - Use setTimeout so that jQuery.fn.dialog file is loaded before checking for its exsistance
setTimeout(function(){
	if(typeof jQuery=='undefined') return;
	if(!jQuery.fn.dialog) return;

	window.alert = function (msg)
	{
		//Hide all select dropdowns for ie6 only
		if(jQuery.browser.msie && jQuery.browser.version=="6.0")
		{
			jQuery('select').css('visibility','hidden');
		}

		//Check if msg is empty
		if(typeof msg == 'string')
		{
			if(!msg || jQuery.trim(msg)=='') return;
		}

		//rand num for id to make each dialog unique
		var dialogId = 'dialog-'+Math.floor(Math.random()*10000);
		//Append new div to the body
		jQuery('body').append(jQuery('<div/>').append(msg).attr({'title':'Alert', 'id':dialogId}));
		//Convert it into a dialog
		jQuery('#'+dialogId).dialog({
			//bgiframe: true,
			modal: true,
			zIndex: 100000000,
			resizable: false,
			buttons: {
				OK: function() {
					jQuery(this).dialog('close');
				}
			},
			close: function() {
				jQuery(this).dialog('destroy').remove();
				//Show the drop downs
				jQuery('select').css('visibility','visible');
			}
		})
		.closest('.ui-dialog').css('font-size',12);
		//Put the small icon with alert msg
		jQuery('#'+dialogId)
			.css('padding-left',4)
			.before(jQuery('<span/>').css({'float':'left', 'margin-left':6, 'margin-top':6}).addClass('ui-icon ui-icon-alert'));
	}
},8000);
