/**
 * The Framework provides global functionality required for the
 * execution of web frameworks, allowing for the creation of sessions
 * and maintaining a global request-queue.
 *
 * @sdoc sdoc/framework.sdoc
 */


Framework = {};


//--------------------------------------------------------/ On-Load /-

(function () {
	var onloads = [];
	var onunloads = [];

	/** @id Framework.performOnLoad */
	Framework.performOnLoad = function (onload) {
		onloads.push (onload);
	};

	/** @id Framework.performOnUnload */
	Framework.performOnUnload = function (onunload) {
		onunloads.push (onunload);
	};

	window.onload = function () {
		Framework.performOnLoad = function (onload) {
			onload ();
		};
		for (var idx = 0; idx < onloads.length; idx++) {
			onloads[idx] ();
		};
	};

	window.onunload = function () {
		for (var idx = 0; idx < onunloads.length; idx++) {
			onunloads[idx] ();
		};
	};
	
	Framework.onResizes = new EventHook ();
	window.onresize = function (ev) {
		Framework.onResizes.notify (ev || window.event);
	}

	Framework.onMouseOvers = new EventHook ();
	document.onmouseover = function (ev) {
		Framework.onMouseOvers.notify (ev || window.event);
	}

	Framework.onClicks = new EventHook ();
	document.onclick = function (ev) {
		Framework.onClicks.notify (ev || window.event);
	}
	
	Framework.onScrolls = new EventHook ();
	window.onscroll = function (ev) {
		Framework.onScrolls.notify (ev || window.event);
	}

	Framework.onMouseMoves = new EventHook ();
	Framework.onMouseUps = new EventHook ();
	Framework.performOnLoad(function () {
		var body = document.getElementsByTagName('body')[0];
		
		body.onmousemove = function (ev) {
			Framework.onMouseMoves.notify (ev || window.event);
		};
		
		body.onmouseup = function (ev) {
			Framework.onMouseUps.notify (ev || window.event);
		}
	});
}) ();



//--------------------------------------------/ Resource Management /-

(function () {
	var resources = {};
	var language = 'NL';

	var initLanguage = function () {
		var qval = QueryValueList ();
		var root = HTML.getElementById ('WebFramework');
		language = qval['language'] || root.getAttribute ('language') || 'NL';
	};

	/** @id Framework.addResource */
	Framework.addResource = function (language, id, resource) {
		var resdata = resources[id] ? resources[id] : [];
		resdata[language] = resource;
		resources[id] = resdata;
	};

	/** @id Framework.getResource */
	Framework.getResource = function (id) {
		var resdata = resources[id];
		if (resdata) {
			var data = resdata[language];
			data = data ? data : resdata['EN'];
			return data;
		}
	};

	/** @id Framework.setLanguage */
	Framework.setLanguage = function (ISOCode) {
		language = ISOCode;
	};

	/** @id Framework.getLanguage */
	Framework.getLanguage = function () {
		return language;
	};

	Framework.performOnLoad (initLanguage);
}) ();



//-----------------------------------------------------/ Unique IDs /-

(function () {
	var ids = {};

	Framework.createUniqueID = function (prefix) {
		ids[prefix] = ids[prefix] || 0;
		return prefix + (ids[prefix]++).toString ();
	}
}) ();



//-------------------------------------------------/ Dynamic Images /-

(function () {
	Framework.imageUrl = function (imageup, size) {
		return (imageup ? httphandler + '?nosession&httphandlercall=WFFileManager&object=' + imageup + (size ? '&size=' + size : '') : '');
	};


	var ie6mode = false;

	Framework.setIE6Mode = function (mode) {
		ie6mode = mode;
	};
	
	Framework.getIE6Mode = function () {
		return ie6mode;
	};
	
	var checkIE6Mode = function () {
		var qval = QueryValueList ();
		ie6mode = (typeof (qval['IE6']) != 'undefined') || (typeof (qval['ie6']) != 'undefined');
	};

	Framework.performOnLoad(checkIE6Mode);
}) ();



(function () {
	//--------------------------------------------------/ Request Queue /-

	var RequestQueue = function () {
		this.queue = [];
		this.paused = 0;
	};

	/** @id RequestQueue.pause */
	RequestQueue.prototype.pause = function () {
		this.paused++;
	};

	/** @id RequestQueue.unpause */
	RequestQueue.prototype.unpause = function () {
		if (this.paused > 0)
			this.paused--;
		processRequests ();
	};

	/** @id RequestQueue.send */
	RequestQueue.prototype.send = function (request) {
		this.queue.push (request);
		processRequests ();
	};

	RequestQueue.prototype.sendNow = function (request) {
		this.queue.unshift (request);
		processRequests ();
	};

	/** @id RequestQueue.repeat */
	RequestQueue.prototype.repeat = function (request) {
		this.queue.unshift (activerequest);
		processRequests ();
	};

	/** @id RequestQueue.next */
	RequestQueue.prototype.next = function () {
		if ((this.queue.length > 0) && (!this.paused)) {
			return this.queue.shift ();
		}
		return null;
	};

	/** @id RequestQueue.clear */
	RequestQueue.prototype.clear = function () {
		while (this.queue.length > 0) {
			var req = this.queue.shift ();
			req.notifyProcessing ();
		}
	};



	/** @id Framework.queue */
	Framework.queue = new RequestQueue ();

	var sessionqueues = {};

	Framework.onSendingRequest = new EventHook ();
	Framework.onRequestCompleted = new EventHook ();
	
	var activerequest = null;

	var nextRequest = function () {
		var req = Framework.queue.next ();
		for (var idx in sessionqueues) {
			if (req) break;
			req = sessionqueues[idx].next ();
		}
		return req;
	};

	var processRequests = function () {
		if ((!activerequest) && (activerequest = nextRequest ())) {
			Framework.onSendingRequest.notify (activerequest);
			activerequest.notifyProcessing ();
			if (activerequest.validate ()) {
				activerequest.dispatch ();
			} else {
				activerequest = null;
				processRequests ();
			}
		}
	};

	Framework.requestHandled = function () {
		Framework.onRequestCompleted.notify (activerequest);
		activerequest = null;
		processRequests ();
	};



	//--------------------------------------------/ Response Processing /-

	var responses = {};

	/** @id Framework.registerResponse */
	Framework.registerResponse = function (up, handler) {
		responses[up] = handler;
	};

	Framework.getResponse = function (up) {
		return responses[up];
	};

	/** @id Framework.processResponses */
	Framework.processResponses = function (request, json) {
		if (!json) {
			Framework.fatalError ('empty response', 'An empty response may indicate that the server is no longer available or that the server has been restarted. Since the client may retain faulty information, it is advised to close and re-open your browser before retrying. If the problem still persists, contact your network administrator.', '');
			return;
		}
	
		try {
			var msgs = eval ('(' + json + ')');
		} catch (exp) {
			Framework.fatalError ('Invalid JSON Data', 'The response from the server contained incorrectly structured JSON data.', json);
		}

		for (var idx = 0; idx < msgs.length; idx++) {
			var msg = msgs[idx];
			if (Framework.getResponse(msg.type)) {
				var session = Framework.sessionById (msg.session);
				Framework.getResponse(msg.type) (session, request, msg.content);
			} else {
				Framework.fatalError ('Unexpected message-type (' + msg.type + ')', 'a call to the server returned an unexpected message-type. This may indicate a version-discrepancy between the web framework httphandler and the javascript.', json);
			}
		}
		Framework.requestHandled ();
	};



	//-----------------------------------------------/ Session Handling /-

	var framework = '';
	var sessions = {};

	/** @id Framework.startSession */
	Framework.startSession = function () {
		var root = HTML.getElementById ('WebFramework');
		framework = root.getAttribute ('application');
		var profile = '';
		if (typeof(webprofile) != 'undefined') {
			profile = webprofile; /* webprofile uit wfsettings.js */ 
		}
		if (framework) {
			new Request.Session (framework, profile, Framework.getLanguage ()).send ();
		}
	};

	Framework.getFrameworkId = function () {
		return framework;
	};

	var onSessionDestroyed = function (session) {
		if (session) {
			delete (sessions[session.id]);
			delete (sessionqueues[session.id]);
		}
	};

	var onCreateSession = function (session, request, content) {
		var queue = new RequestQueue ();
		var session = new Session (content.id, queue, content.newaccount, content.recoverpassword);
		session.onDestroy.add (onSessionDestroyed);
		sessionqueues[content.id] = queue;
		sessions[content.id] = session;
	};

	Framework.registerResponse ('6EDB::30::6EDB::3372', onCreateSession);

	 var destroySessions = function () {
		for (var idx in sessions) {
			sessions[idx].destroy (true);
		}
	};

	Framework.sessionById = function (id) {
		return sessions[id];
	};

	Framework.performOnLoad (Framework.startSession);
	Framework.performOnUnload (destroySessions);



	//-------------------------------------------------/ Error-handling /-

	/** @id Framework.onFatalError */
	Framework.onFatalError = new EventHook ();

	/** @id Framework.fatalError */
	Framework.fatalError = function (title, message, additional) {
		Framework.onFatalError.notify ();
		destroySessions ();
		fatalError (title, message, additional);
	};
}) ();



//-----------------------------------------------------/ ClientInfo /-

(function () {
	var gatherClientInfo = function () {
		var s = screen, n = navigator;
		var info = {
			'width': s.width,
			'height': s.height,
			'availwidth': s.availWidth,
			'availheight': s.availHeight,
			'colordepth': s.colorDepth,
			'platform': n.platform,
			'appcodename': n.appCodeName,
			'appname': n.appName,
			'appversion': n.appVersion,
			'java': n.javaEnabled (),
			'useragent': n.userAgent
		};

		new Request.ClientInfo (info).send ();
	};

	Framework.performOnLoad (gatherClientInfo);
}) ();



//-----------------------------------------------------/ Status-Bar /-

(function () {
	var status = null;
	
	var initStatus = function () {
		status = HTML.getElementById ('WFStatus');
		if (!status) {
			status = HTML.createDiv ('nav-status');
			var body = document.getElementsByTagName("body")[0];
			body.insertBefore (status, body.firstChild);
		}
	};

	/** @id Framework.addStatelet */
	Framework.addStatelet = function (statelet) {
		HTML.add (status, statelet.getHTMLRoot ());
	};

	/** @id Framework.removeStatelet */
	Framework.removeStatelet = function (statelet) {
		HTML.remove (status, statelet.getHTMLRoot ());
	};

	Framework.performOnLoad (initStatus);	
}) ();



//-----------------------------------------------/ Throbber/Message /-

(function () {
	var throbber = null;
	var message = null;

	var onSendingRequest = function (req) {
		message.setMessage (req.status);
		throbber.activate ();
	};

	var onRequestCompleted = function (req) {
		message.setMessage ('ready');
		throbber.deactivate ();
	};

	var onFatalError = function () {
		message.setMessage ('error');
		throbber.error ();
	};
	
	var initThrobber = function () {
		throbber = new Statelets.Throbber ();
		Framework.addStatelet (throbber);
		message = new Statelets.Message ();
		Framework.addStatelet (message);
		Framework.onSendingRequest.add (onSendingRequest);
		Framework.onRequestCompleted.add (onRequestCompleted);
		Framework.onFatalError.add (onFatalError);
	};
	
	Framework.performOnLoad (initThrobber);
}) ();
