(function() {
	//
	if (!window.bb)
		throw 'Error loading dashboard.js. dashboard.js requires the Backbase engine to be loaded';

	if (!bb.dashboard)
		bb.dashboard = {};

	bb.dashboard.query	= function(sQuery) {
		switch (sQuery.substr(0, 1)) {
			case "#":
				return [document.getElementById(sQuery.substr(1))];
			case ".":
				return document.getElementsByClassName(sQuery.substr(1));
			default:
				return document.getElementsByTagName(sQuery);
		}
	};

	//Localisation support
	bb.dashboard.locale = {};

	bb.dashboard.getLocale = function(sString){
		return bb.dashboard.locale[sString] || sString;
	};


	//Generic dashboard settings
	bb.dashboard._prefs = {
		//Only for dashboard, all possible settings == default once also!
		resizable: true,
		draggable: true,
		animation: 300,
		multiBoard: true,
		gadgetMargin: 8,
		proxyURL: 'dashboard/services/proxy.php?url=',
		syncURL: 'session.php',
		syncType: 'none',
		gadgetTemplate: null,
		gadgetButtons: [
			['close', 'Close',],
			['preferences', 'Preferences', 'Edit', 'Close Edit'],
			['options', 'Options'],
			['refresh', 'Refresh'],
			['toggle', 'Toggle']
		],
		defaultGadget: {
			//All possible gadget settings == default once also!
			'closable': 'true',
			'denyInsert': 'none',
			'draggable': 'true',
			'minimizable': 'true',
			'maximizable': 'true',
			//'className': '',
			'editable': 'true',
			'optionsMenu': 'true',
			'refreshable': 'true',
			'autoRefresh': '0',
			'maximizedMode': 'exactfit'
		},
		gadget:	{}
	};

	bb.dashboard.setGlobalSetting = function(sType, oObject, oValue){
		var oSettings = bb.dashboard._prefs;
		switch (sType) {
			case 'dashboard':
				if (typeof oObject == 'object') {
					for (var i in oObject)
						oSettings[i] = oObject[i];
				} else if(typeof oObject == 'string') {
					oSettings[oObject] = oValue;
				}
			break;
			case 'gadget':
				if (typeof oObject == 'object') {
					for (var i in oObject)
						oSettings.gadget[i] = oObject[i];
				} else if(typeof oObject == 'string') {
					oSettings.gadget[oObject] = oValue;
				}
			break;
		}
	}



	bb.dashboard.gadget = {};

	bb.dashboard.gadget.setTitle = function(oGadget, sTitle, sHref) {
		if (oGadget._controller)
			oGadget._controller.setAttribute('title', sTitle);
		else
			document.title = sTitle;
	}

	bb.dashboard.gadget.getTitle = function(oGadget) {
		return oGadget._controller ? oGadget._controller.getAttribute('title') : document.title;
	}

	bb.dashboard.gadget.getGadgetFromView = function(oElement) {
		if(window.__GADGET__)
			return __GADGET__;
		else {
			var oCon = 	bb.getControllerFromView(oElement);
			while( oCon && !oCon.instanceOf('http://www.backbase.com/2008/dashboard', 'gadget') )
				oCon = oCon.getProperty('parentNode');
			return oCon ? oCon.getProperty('gadget') : null;

		}
	}

	bb.dashboard.gadget.savePreference = function(oInput) {
		var	oContoller = bb.getControllerFromView(oInput),
			oGadgetClass = oContoller.getProperty('gadgetClass'),
			oGadget = oContoller.getProperty('gadget'),
			sTagName = String(oInput.tagName).toLowerCase();
		//If we require submit but the form wasnt submitted do not register any change
		if(oGadgetClass.requireSubmit && sTagName != 'form') return;

		switch ( sTagName ) {
			case 'input':
			case 'select':
				var sValue = (oInput.type == 'radio' || oInput.type == 'checkbox') ? String(oInput.checked) : oInput.value;
				oGadget.setPreferenceForKey(oInput.name, sValue);
			break;
			case 'form':
				for (var sPreference in oGadgetClass.preferences) {
					oPreference	= oGadgetClass.preferences[sPreference];
					if (oPreference.type == 'hidden')
						continue;
					var oElm = oInput.elements[sPreference];

					var sValue = (oElm.type == 'radio' || oElm.type == 'checkbox') ? String(oElm.checked) : oElm.value;
					oGadget.setPreferenceForKey(sPreference, sValue);
				}
			break;
		}
		// Notify Gadget Instance: change
		var oEvent	= bb.document.createEvent("CustomEvent");
		oEvent.initEvent("change", false, false, null, null);
		oContoller.dispatchEvent(oEvent);
	}

	bb.dashboard.gadget.setIcon = function(oGadget, sIcon) {
		if (oGadget._controller) {
			oGadget._controller.setAttribute('icon', sIcon);
		}
	}

	bb.dashboard.gadget.setBody = function(oGadget, sContent) {
		bb.dashboard.gadget.getBody(oGadget).innerHTML = sContent;
	}
	bb.dashboard.gadget.getBody = function(oGadget) {
		if(oGadget._controller)
			return oGadget._controller.viewGate;
		else
			return document.body;
	}
	bb.dashboard.gadget.getPreferenceLabelForValue = function(oGadget, sKey, sValue) {
		var oClass = oGadget._controller.getProperty('gadgetClass');
		var oPreference = oClass.preferences[sKey];
		for (var i in oPreference.values) {
			if(	oPreference.values[i].value == sValue)
				return oPreference.values[i].label;
		}
	};

	bb.dashboard.gadget.showPreferences = function(oGadget){
		if(oGadget._controller)
			oGadget._controller.showPreferences();
	}

	bb.dashboard.gadget.hidePreferences = function(oGadget){
		if(oGadget._controller)
			oGadget._controller.hidePreferences();
	}

	bb.dashboard.gadget.setState = function(oGadget, sState){
		if(oGadget._controller)
			oGadget._controller.setAttribute('state', sState);
	}
	bb.dashboard.gadget.getState = function(oGadget) {
		if(oGadget._controller)
			return oGadget._controller.getAttribute('state');
	}
	// Publish/Subscribe Mechanism for Gadgets
	bb.dashboard.events	= {};

	bb.dashboard.events.publish	= function(sEvent, oData) {

	};
	bb.dashboard.events.subscribe	= function(sEvent, fCallback) {

	};
	bb.dashboard.events.unsubscribe	= function(sEvent, fCallback) {

	};



	//--------------------------------
	bb.dashboard.resolveUri = function (sUri, sBaseUri) {
	//--------------------------------
		if (sUri == '' || sUri.charAt(0) == '#')
			return sUri;

		//
		var hUri = bb.dashboard.getUriComponents(sUri);
		if (hUri.scheme)
			return sUri;

		var hBaseUri = bb.dashboard.getUriComponents(sBaseUri);
		hUri.scheme = hBaseUri.scheme;

		if (!hUri.authority) {
			hUri.authority = hBaseUri.authority;
			if (hUri.path.charAt(0) != '/') {
				var aUriSegments = hUri.path.split('/');
				var aBaseUriSegments = hBaseUri.path.split('/');
				aBaseUriSegments.pop();
				var iBaseUriStart = aBaseUriSegments[0] == '' ? 1 : 0;
				for (var i = 0, iLength = aUriSegments.length; i < iLength; i++) {
					if (aUriSegments[i] == '..') {
						if (aBaseUriSegments.length > iBaseUriStart)
							aBaseUriSegments.pop();
						else {
							aBaseUriSegments.push(aUriSegments[i]);
							iBaseUriStart++;
						}
					}
					else
					if (aUriSegments[i] != '.')
						aBaseUriSegments.push(aUriSegments[i]);
				}
				if (aUriSegments[--i] == '..' || aUriSegments[i] == '.')
					aBaseUriSegments.push('');
				hUri.path = aBaseUriSegments.join('/');
			}
		}
		var aResult = [];
		if (hUri.scheme) aResult.push( hUri.scheme + ':');
		if (hUri.authority) aResult.push('//' + hUri.authority);
		if (hUri.path) aResult.push(hUri.path);
		if (hUri.query) aResult.push('?' + hUri.query);
		if (hUri.fragment) aResult.push('#' + hUri.fragment);

		return aResult.join('');
	}

	//--------------------------------
	bb.dashboard.getUriComponents	= function(sUri) {
	//--------------------------------
		// Cache implemented by request in bug 9144
		var
			oCache = bb.dashboard.getUriComponents._cache,
			c = oCache[sUri] || (oCache[sUri] = sUri.match(bb.dashboard.getUriComponents._regExpUri));
		return {'scheme': c[2], 'authority': c[4], 'path': c[5], 'query': c[7], 'fragment': c[9]};
	};
	bb.dashboard.getUriComponents._cache = {}; // cache for matches
	bb.dashboard.getUriComponents._regExpUri	= new RegExp('^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?');


	// Proxy
	bb.dashboard.proxy	= {};

	bb.dashboard.proxy.load = function(sMethod, sUrl, oParams, fCallback, asynch) {
		var oRequest = new XMLHttpRequest();
		//Cross-domain rewrite the url
		if( sUrl.indexOf('://') != -1 ) {
			sUrl = bb.dashboard._prefs.proxyURL + encodeURIComponent(sUrl);
			if (bb.dashboard.standalone) sUrl = '../../'+sUrl;

		}
		asynch = (asynch === false)?false:true;
		oRequest.open(sMethod, sUrl, asynch);

		oRequest.onreadystatechange = function(){
			if (oRequest.readyState == 4) {
				//if(oRequest.status == 200) {
					if(fCallback)
						fCallback(oRequest);
				//}
			}
		}
		oRequest.send(null);

		return oRequest;
	};


	var oOnceFiles = {};

	bb.dashboard.proxy.requireOnce = function (sUrl, fCallbackAlways, fCallbackOnce) {
		var oFile = oOnceFiles[sUrl];
		if (oFile) {
			if (oFile.loaded) {
				//This MUST be asynchronous because multiple files might get added in one go,
				if(fCallbackAlways)
					setTimeout(	function(){ fCallbackAlways(oFile.oRequest); }, 0)
			}
			else
				oFile.queue.push(fCallbackAlways);
		} else {
			var oFile = {};
			oFile.loaded = false;
			oFile.queue = [fCallbackAlways];
			oOnceFiles[sUrl] = oFile;
			oFile.oRequest = bb.dashboard.proxy.load('GET', sUrl, null, function(oRequest) {
				oFile.loaded = true;
				if(fCallbackOnce)
					fCallbackOnce(oRequest);
				while (oFile.queue.length)
					oFile.queue.shift()(oRequest);
			});
		}
	};
})();