/**
 * Contains the Javascript class Sitebox.
 *
 * @copyright	CARE Internet Services B.V. All Rights Reserved
 * @internal	$Id: Sitebox.js 889 2010-01-26 14:53:39Z niek $
 * @internal	$Date: 2010-01-26 15:53:39 +0100 (Tue, 26 Jan 2010) $
 * @author		$Author: niek $
 * @version		$Revision: 889 $
 */

/**
 * Sitebox class with basic static functions.
 */
Sitebox = {

	/**
	 * Include a Javascript file (if not already included).
	 *
	 * @param	string	url
	 *
	 * @return	boolean	true when included, false if already included
	 */
	includeJavascriptOnce: function(url)
	{
		var loadedScripts = document.getElementsByTagName('script');
		for (var i = 0; i < loadedScripts.length; i++)
		{
			if (loadedScripts[i].src && getNodeAttribute(loadedScripts[i], 'src').indexOf(url) == 0)
			{
				return false;
			}
		}
		script = createDOM('SCRIPT', {'src': url, 'type': 'text/javascript'});
		appendChildNodes(document.getElementsByTagName('head')[0], script);
		return true;
	}, // function includeJavascriptOnce

	/**
	 * Include a CSS stylesheet (if not already included).
	 *
	 * @param	string	url
	 * @param	string	media	Optional media type
	 *
	 * @return	boolean	true when included, false if already included
	 */
	includeStylesheetOnce: function(url, media)
	{
		var loadedStylesheets = document.getElementsByTagName('link');
		for (var i = 0; i < loadedStylesheets.length; i++)
		{
			if (loadedStylesheets[i].rel == 'stylesheet' && loadedStylesheets[i].href && getNodeAttribute(loadedStylesheets[i], 'href').indexOf(url) == 0)
			{
				return false;
			}
		}
		var attr = {'href': url, 'type': 'text/css', 'rel': 'stylesheet'};
		if (media)
		{
			attr.media = media;
		}
		stylesheet = createDOM('LINK', attr);
		appendChildNodes(document.getElementsByTagName('head')[0], stylesheet);
		return true;
	}, // function includeStylesheetOnce

	/**
	 * Show the progress indicator.
	 *
	 * @param	string	msg
	 */
	showProgressIndicator: function(msg)
	{
		if (!$('sb-progress-indicator'))
		{
			/* Center the indicator horizontal and vertical. */
			var bodyDimensions = getViewportDimensions();
			/* As both 0 as well as undefined evaluate to false,
			   first initialize the values to 0. That way we have
			   a numeric value if none of the methods works */
			var scrollX = 0;
			var scrollY = 0;
			/* Mozilla has a documentElement.scroll[Left|Top] with a permanent
			   value of 0 so checking for != undefined won't work. Not entering
			   any conditional statement here if the scrollposition is (0,0) is
			   no problem as that is already set as default value */
			/* scrollX, scrollY is W3C, scrollLeft, scrollTop is IE specific */
			if (document.documentElement
				&& (document.documentElement.scrollLeft || document.documentElement.scrollTop ))
			{
				//IE 6 (in standards compliant mode)
				scrollX = document.documentElement.scrollLeft;
				scrollY = document.documentElement.scrollTop;
			}
			else if (document.body && ( document.body.scrollLeft || document.body.scrollTop ))
			{
				//IE 4, 5 & 6 (in non-standards compliant mode)
				scrollX = document.body.scrollLeft;
				scrollY = document.body.scrollTop;
			}
			else if ( window.scrollX || window.scrollY )
			{
				scrollX = window.scrollX;
				scrollY = window.scrollY;
			}
			attributes = {
				'id': 'sb-progress-indicator',
				'style': {
					'zIndex': '1000000000',
					'position': 'absolute',
					'left': (Math.round(bodyDimensions.w / 2) + scrollX) + 'px',
					'top': (Math.round(bodyDimensions.h / 2) + scrollY) + 'px',
					'margin': '-28px 0 0 -105px',
					'width': '200px',
					'border': '2px solid #000',
					'padding': '10px 10px 10px 10px',
					'font': 'bold 11pt sans-serif',
					'background': '#FFF'}};
			indicator = DIV(attributes, IMG({'src': sbFrameworkUrl + '/images/Sitebox/ProgressIndicator/indicator.gif', 'style': {'marginRight': '5px', 'verticalAlign': 'text-top'}}), msg);
			appendChildNodes(currentDocument().body, indicator);
		}
		else
		{
			this.updateProgressIndicator(msg);
		}
	}, // function showProgressIndicator

	/**
	 * Update the progress indicator message.
	 *
	 * @param	string	msg
	 */
	updateProgressIndicator: function(msg)
	{
		if ($('sb-progress-indicator'))
		{
			$('sb-progress-indicator').childNodes[1].nodeValue = msg;
		}
	}, // function updateProgressIndicator

	/**
	 * Hide the progress indicator.
	 */
	hideProgressIndicator: function()
	{
		if ($('sb-progress-indicator'))
		{
			removeElement($('sb-progress-indicator'));
		}
	}, // function hideProgressIndicator

	/**
	 * Maximum number of tries to execute a Javascript call.
	 */
	callMaxTries: 100,

	/**
	 * Interval in ms between tries to execute a Javascript call.
	 */
	callInterval: 10,

	/**
	 * Queue for Javascript calls.
	 */
	callCounter: new Array(),

	/**
	 * Tries to execute a Javascript call.
	 *
	 * @param	function	f
	 * @param	int			id
	 *
	 * @throws	Error
	 */
	call: function(f, id)
	{
		if (id == undefined)
		{
			id = this.callCounter.length;
			this.logDebug('new function call id: ' + id);
			this.callCounter[id] = 0;
		}
		try
		{
			f();
		}
		catch(e)
		{
			/* Only retry if it's a ReferenceError. */
			if (e instanceof Error || e instanceof ReferenceError || e instanceof TypeError)
			{
				if (this.callCounter[id] < this.callMaxTries)
				{
					window.setTimeout('Sitebox.call(' + f + ', ' + id + ');', this.callInterval);
					this.callCounter[id] += 1;
					this.logDebug('function call ' + id + ' failed: ' + this.callCounter[id]);
				}
				else
				{
					this.logDebug('function call ' + id + ' aborted: ' + this.callCounter[id] + ' tries.');
					this.logDebug('function called: ' + f);
					/* Rethrow exeption, and let the browser/log panel catch it. */
					throw e;
				}
			}
			else
			{
				/* If it's any other type of exception, rethrow it
				 * and let the browser/log panel catch it.
				 */
				throw e;
			}
		}
	}, // function call

	/**
	 * Static shortcut function for logging an emergency to the debug panel.
	 *
	 * @param	string	message
	 */
	logEmerg: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'emerg', toISOTimestamp(new Date()));
		}
	}, // function logEmerg

	/**
	 * Static shortcut function for logging an alert to the debug panel.
	 *
	 * @param	string	message
	 */
	logAlert: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'alert', toISOTimestamp(new Date()));
		}
	}, // function logAlert

	/**
	 * Static shortcut function for logging a critical message to the debug panel.
	 *
	 * @param	string	message
	 */
	logCrit: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'crit', toISOTimestamp(new Date()));
		}
	}, // function logCrit

	/**
	 * Static shortcut function for logging an error message to the debug panel.
	 *
	 * @param	string	message
	 */
	logError: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'error', toISOTimestamp(new Date()));
		}
	}, // function logError

	/**
	 * Static shortcut function for logging a warning message to the debug panel.
	 *
	 * @param	string	message
	 */
	logWarning: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'warning', toISOTimestamp(new Date()));
		}
	}, // function logWarning

	/**
	 * Static shortcut function for logging a notice to the debug panel.
	 *
	 * @param	string	message
	 */
	logNotice: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'notice', toISOTimestamp(new Date()));
		}
	}, // function logNotice

	/**
	 * Static shortcut function for logging an info message to the debug panel.
	 *
	 * @param	string	message
	 */
	logInfo: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'info', toISOTimestamp(new Date()));
		}
	}, // function logInfo

	/**
	 * Static shortcut function for logging a debug message to the debug panel.
	 *
	 * @param	string	message
	 */
	logDebug: function(message)
	{
		if (sbDebugPanel)
		{
			sbDebugPanel.log(message, 'debug', toISOTimestamp(new Date()));
		}
	} // function logDebug

}; // class Sitebox

/**
 * Prevents javascript errors if no debug panel available
 */
var sbDebugPanel = false;