/*
 * Aplix BONDI loader
 * TODO sync http://g.webvm.net/?p=widgetmanager;a=blob;f=linux/bondi.loader
 */

if (typeof bondi == 'undefined') {
	(function() {

		var defaults = {
			pluginParams: {},
			instanceParams: {},
			mimetype: 'application/x-vnd-aplix-webvm'
		};

		var root = {};
		root.ob = addPlugin(defaults.pluginParams);
		if (!root.ob) { return; }

		window.bondi = {};
		bondi.ext = {}; // For Test framework's bondi.ext.setPolicy

		bondi.DeviceAPIError = {};
		bondi.DeviceAPIError.UNKNOWN_ERROR = 10000;
		bondi.DeviceAPIError.INVALID_ARGUMENT_ERROR = 10001;
		bondi.DeviceAPIError.NOT_FOUND_ERROR = 10002;
		bondi.DeviceAPIError.PENDING_OPERATION_ERROR = 10003;
		bondi.DeviceAPIError.IO_ERROR = 10004;
		bondi.DeviceAPIError.NOT_SUPPORTED_ERROR = 10005;
		bondi.SecurityError = {};
		bondi.SecurityError.PERMISSION_DENIED_ERROR = 20000;

		/* define enums */
		bondi.defs = {
			state: {
				created: 0,
				initialised: 1,
				loading: 2,
				loaded: 3,
				starting: 4,
				started: 5,
				exited: 6,
				aborted: 7,
				failed: 8,
				denied: 9
			},
			status: {
				ok: 0,
				inuse: -78
			}
		};

		/*
		 * add any private variables used by global exported functions
		 * as children of root
		 */
		root.queue = {
			documentLoad: {queue: [], loaded: false},
			documentUnload: {queue: [], loaded: false}
		};

		/*
		 * second closure creates private instance-wide scope
		 */
		function createInstance(name) {

			var localroot = {};

			/*
			 * add any private variables used by instance-wide exported functions
			 * as children of localroot
			 */
			localroot.name = name;

			return localroot;
		}

		/*
		 * here declare and implement any private functions
		 * used by global exported functions
		 */

		function makeURI(name,version,params){
			return name+'?v='+version+encodeParams(params)+defaults.params;
		}

		function encodeParams(params){
			var b='';
			if(params!==undefined){
				for(var d in params){
					/* TODO check validity of param */
					b+='&'+d+'='+encodeURIComponent(params[d]);
				}
			}
			return b;
		}

		function registerLoadHandlers(c, d) {
			var a = window;
			if(a.addEventListener){
				a.addEventListener('unload', d, false);
				if(document.addEventListener){
					document.addEventListener('DOMContentLoaded', c, false);
				} else {
					a.addEventListener('load', c, false);
				}
			} else if(a.attachEvent){
				a.attachEvent('onload', c);
				a.attachEvent('onunload', d);
			} else {
				a.onload = c;
				a.onunload = d;
			}
		}

		function runOnLoad(f,phase,idx) {
			if (idx === undefined) {
				idx = 100;
			}
			if (phase === undefined) {
				phase = 'documentLoad';
			}
			var q = root.queue[phase];
			if (q.loaded) {
				f();
			} else {
				q = q.queue;
				q[q.length] = [idx,f];
			}
		}

		function runQueue(queue) {
			if (queue.loaded) {
				return;
			}
			var q = queue.queue;
			q.sort(function(a,b) { return (a[0]-b[0]); });
			for (var i = 0; i< q.length; i++) {
				try { q[i][1](); }
				catch(e) {}
			}
			queue.loaded = true;
			delete queue.queue;
		}

		registerLoadHandlers(
			function() { runQueue(root.queue.documentLoad); },
			function() { runQueue(root.queue.documentUnload); }
		);

		function includeScriptByURI(uri){
			var headID = document.getElementsByTagName('head')[0];
			var newScript = document.createElement('script');
			newScript.type = 'text/javascript';
			newScript.src = uri;
			headID.appendChild(newScript);
		}

		function addPlugin(params) {
			try {
				var ob = new ActiveXObject('Aplix.WebVM');
				root.activex = true;
				return ob;
			} catch (e) {
				if (navigator.mimeTypes && navigator.mimeTypes[defaults.mimetype]) {
					var ob = document.createElement('object');
					ob.width = 0; ob.height = 0;
					ob.type = defaults.mimetype;
					for(var d in params) {
						var param = document.createElement('param');
						ob.appendChild(param);
						param.name = d;
						param.value = params[d];
					}
					document.documentElement.appendChild(ob);
					return ob;
				}
			}
		}

		function addInstance(successCallback, errorCallback, name) {
			runOnLoad(function() {addInstanceNow(successCallback, errorCallback, name);}, 'documentLoad', 10);
		}

		function addInstanceNow(successCallback, errorCallback, name) {

			/* create local root */
			var instanceRoot = createInstance(name);
			var _bondi = window.bondi;

			/* define callbacks */
			var baseCallback = function(state) {
				if(state == _bondi.defs.state.aborted || state == _bondi.defs.state.failed) {
					if(errorCallback) {
						errorCallback('Loading of feature <' + name + '> failed; state = ' + state);
					}
					return;
				}
				if(state == _bondi.defs.state.denied) {
					if(errorCallback) {
						errorCallback('Loading of feature <' + name + '> denied');
					}
					return;
				}
			};
			var startCallback = function(state) {
				if(state == _bondi.defs.state.started) {
					try {
						var feature = root.ob.getFeature(name);
						var featureRoot = root.ob.getFeatureName(name);
						if (!(featureRoot === undefined)) {
							var ob = bondi;
							featureRoot = featureRoot.split('.').reverse();
							while (featureRoot.length > 1) {
								var next = featureRoot.pop();
								if (ob[next] === undefined)
									ob[next] = {};
								ob = ob[next];
							}
							ob[featureRoot[0]] = feature;
						}
						if(successCallback) {
							successCallback();
						}
					}
					catch(e) { }
					return;
				}
				baseCallback(state);
			};

			var loadCallback = function(state) {
				if(state == _bondi.defs.state.loaded) {
					// Assign result to return value on ActiveX objects for Pocket IE
					var result = root.ob.startFeature(name, startCallback);
					return;
				}
				baseCallback(state);
			};

			/* load the feature */
			var loadStatus = root.ob.loadFeature(name, {}, loadCallback);
			if(loadStatus != _bondi.defs.status.ok) {
				if(errorCallback) {
					errorCallback('Plugin failed to start; status = ' + loadStatus);
				}
			}
		}

		/*
		* here export the exported functions
		* by making them properties of the global root
		*/
		bondi.requestFeature = addInstance;
		bondi.ext.releaseFeature = function(name) {}
		bondi.ext.getProperty = function(name) { return root.ob.getProperty(name); };
		bondi.ext.getFeature = function(name) { return root.ob.getFeature(name); };
		bondi.ext.setPolicy = function(txt) { return root.ob.setPolicy(txt); };
		bondi.runOnLoad = runOnLoad;
	})();
}
