var isSubmited = false;
var workspaceFormWarning = false;

var JSONRPCBridge = null;

function getJSONRPCBridge() {
	if (JSONRPCBridge != null) {
		return JSONRPCBridge;
	}
	try {
		JSONRPCBridge = new JSONRpcClient("/JSON-RPC?versionFilter=LatestCommittedFilter");
	} catch(e) {
		alert("Exception\nName: " + e.name + "\nMessage: " + e.message + "\nDescription: " + e.description);
	}
	return JSONRPCBridge;
}

function openwin(url, page, width, height) {
	if (!page) page = '_blank';
	page = page.replace(/[^a-zA-Z0-9_]/g, 'x');
	if (!width) width = 600;
	if (!height) height = 400;
	var win = window.open(url, page, 'dependent=no,height=' + height + ',width=' + width + ',location=no,menubar=no,resizable=yes,scrollbars=yes,status=yes,toolbar=no,left=100,top=100,screenX=100,screenY=100');
	if (win) {
		win.focus();
	}
	return win;
}

function openlink(url) {
	document.location.href = url;
}

function exec(param1, param2, param3, param4, param5) {
	if (isSubmited) {
		return;
	}
	isSubmited = true;
	var form = document.forms['workspace'];
	if (!form) {
		if (!workspaceFormWarning) {
			workspaceFormWarning = true;
			alert("Workspace Form not found");
		}
		return;
	}
	if (form) {
		if (form.elements['param1'] && (param1 == 0 || param1)) {
			form.elements['param1'].value = param1;
		}
		if (form.elements['param2'] && (param2 == 0 || param2)) {
			form.elements['param2'].value = param2;
		}
		if (form.elements['param3'] && (param3 == 0 || param3)) {
			form.elements['param3'].value = param3;
		}
		if (form.elements['param4'] && (param4 == 0 || param4)) {
			form.elements['param4'].value = param4;
		}
		if (form.elements['param5'] && (param5 == 0 || param5)) {
			form.elements['param5'].value = param5;
		}
		if (form.elements['xpos'] && form.elements['ypos']) {
			if (document.body && document.body.scrollLeft) {
				form.elements['xpos'].value = document.body.scrollLeft;
			} else if (window.pageXOffset) {
				form.elements['xpos'].value = window.pageXOffset;
			} else if (document.documentElement && document.documentElement.scrollLeft) {
				form.elements['xpos'].value = document.documentElement.scrollLeft;
			} else {
				form.elements['xpos'].value = 0;
			}
			if (document.body && document.body.scrollTop) {
				form.elements['ypos'].value = document.body.scrollTop;
			} else if (window.pageYOffset) {
				form.elements['ypos'].value = window.pageYOffset;
			} else if (document.documentElement && document.documentElement.scrollTop) {
				form.elements['ypos'].value = document.documentElement.scrollTop;
			} else {
				form.elements['ypos'].value = 0;
			}
		}
		/*
		 if (form.elements['__controls__']) {
		 form.elements['__controls__'].value = collectControlNames(form);
		 }
		 */
		var button = form.elements['workspaceHiddenSubmitButton'];
		if (button) {
			button.click();
		} else {
			form.submit();
		}
	}
}

/*
 function collectControlNames(form) {

 var names = new Object();

 // find all "input" elements in form
 var inputs = form.getElementsByTagName("input");
 for (var i = 0; i < inputs.length; i++) {
 var input = inputs[i];
 if (!input.name) continue;
 names[input.name] = true;
 }

 // find all "textarea" elements in form
 var textareas = form.getElementsByTagName("textarea");
 for (var i = 0; i < textareas.length; i++) {
 var textarea = textareas[i];
 if (!textarea.name) continue;
 names[textarea.name] = true;
 }

 // find all "select" elements in form
 var selects = form.getElementsByTagName("select");
 for (var i = 0; i < selects.length; i++) {
 var select = selects[i];
 if (!select.name) continue;
 names[select.name] = true;
 }

 var result = '';
 for (var name in names) {
 result += name + ";";
 }

 return result;
 }
 */

function focusOnFirstField() {
	var form = document.forms['workspace'];
	if (form) {
		var elements = form.elements;
		if (elements && elements.length) {
			for (var i = 0; i < elements.length; i++) {
				var element = elements[i];
				if (focusOnElement(element)) {
					return;
				}
			}
		}
	}
}

function focusOnField(names) {
	var form = document.forms['workspace'];
	var fields = names.split(',');
	if (form && fields) {
		var elements = form.elements;
		if (elements && elements.length) {
			for (var i = 0; i < elements.length; i++) {
				var element = elements[i];
				if (element.type) {
					var name = element.name;
					for (var j = 0; j < fields.length; j++) {
						if (fields[j] == name) {
							if (focusOnElement(element)) {
								return;
							}
						}
					}
				}
			}
		}
	}
}

function focusOnFieldId(id) {
	var element = document.getElementById(id);
	focusOnElement(element);
}

function focusOnElement(element) {
	if (element && element.type) {
		if (element.disabled) {
			// skip
		} else if (element.readOnly) {
			// skip
		} else {
			var type = element.type;
			if (type == 'text' || type == 'textarea' || type == 'password') {
				try {
					element.focus();
					element.select();
					return true;
				} catch(e) {
					// skip
				}
			} else if (type == 'select-one' || type == 'select' || type == 'radio' || type == 'checkbox') {
				try {
					element.focus();
					return true;
				} catch(e) {
					// skip
				}
			}
		}
	}
	return false;
}

function resetForms() {
	// reset all forms in the document
	// this method is called to prevent firefox from restoring form field values on F5 reload
	var forms = document.getElementsByTagName("form");
	for (var f = 0; f < forms.length; f++) {
		try {
			forms[f].reset();
		} catch(ex) {
			// ignore
		}
	}
}

function openLabelManager(languageId) {
	var url = '/frontend/labels.jsp';
	if (languageId) {
		url += '?selectedLanguageId=' + languageId;
	}
	openwin(url, 'LabelManager', 900, 600);
}

var KeepAlive = {

	interval: 5 * 60 * 1000,

	timeout: null,

	start: function(interval) {
		KeepAlive.interval = interval;
		KeepAlive.schedule();
	},

	schedule: function() {
		KeepAlive.timeout = window.setTimeout('KeepAlive.send()', KeepAlive.interval);
	},

	unschedule: function() {
		window.clearTimeout(KeepAlive.timeout);
	},

	send: function() {

		try {

			var request = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0");

			request.onreadystatechange = function() {
				if (request.readyState == 4) {
					KeepAlive.handleResponse(request);
				}
			};

			// send request to KeepAliveServlet mapped to path /keepalive
			request.open('GET', '/keepalive', true);
			request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			request.setRequestHeader("Connection", "close");
			request.send('');

		} catch(ex) {
			// ignore any exception
		}

	},

	handleResponse: function(request) {
		KeepAlive.schedule();
	}

};

var shortcuts = new Array();

function registerShortcut(keyCode, action, ctrlKey, altKey, shiftKey) {
	var shortcut = new Object();
	shortcut.keyCode = keyCode;
	shortcut.action = action;
	shortcut.ctrlKey = ctrlKey;
	shortcut.altKey = altKey;
	shortcut.shiftKey = shiftKey;
	shortcuts.push(shortcut);
}

function executeShortcuts(keyCode, ctrlKey, altKey, shiftKey) {
	var found = false;
	for (var s = 0; s < shortcuts.length; s++) {
		var shortcut = shortcuts[s];
		if (shortcut.keyCode != keyCode) continue;
		if (shortcut.ctrlKey != ctrlKey) continue;
		if (shortcut.altKey != altKey) continue;
		if (shortcut.shiftKey != shiftKey) continue;
		found = true;
		eval(shortcut.action);
	}
	return found;
}

document.onkeydown = keyHandler;

function registerOnEnter(action) {
	registerShortcut(13, action, false, false, false);
}

function keyHandler(e) {
	if (e) {
		event = e;
	}
	var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;

	// cancel backspace key events to prevent triggering the browser's 'Back' action
	// exception: in input fields of type text, textarea or password
	if (keyCode == 8) {
		var element = event.srcElement ? event.srcElement : event.target;
		if (element) {
			var type = element.type;
			if (type != "text" && type != "textarea" && type != "password") {
				cancelEvent(event);
				return;
			}
		}
	}

	// do not process enter key events on textareas and buttons
	if (keyCode == 13) {
		var element = event.srcElement ? event.srcElement : event.target;
		if (element) {
			var type = element.type;
			if (type == "textarea" || type == "button" || type == "submit" || type == "reset") {
				return;
			}
		}
	}

	var found = executeShortcuts(keyCode, event.ctrlKey, event.altKey, event.shiftKey)
	if (found) {
		cancelEvent(event);
	}

}

function cancelEvent(event) {
	event.cancelBubble = true;
	event.returnValue = false;
	if (event.cancelable) {
		event.preventDefault();
		event.stopPropagation();
	}
}

function isEnterKeyEvent(e) {
	if (!e) {
		e = event;
	}
	var keyCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
	return keyCode == 13;
}

function queueEvent(componentPath, eventType, parameters) {
	if (isSubmited) {
		return;
	}
	var form = document.forms['workspace'];
	if (!form) {
		if (!workspaceFormWarning) {
			workspaceFormWarning = true;
			alert("Workspace Form not found");
		}
		return;
	}
	if (form) {
		var events = form.elements['__events__'];
		if (events) {
			if (events.value) {
				events.value += ";" + componentPath + "," + eventType;
			} else {
				events.value = componentPath + "," + eventType;
			}
			if (parameters && parameters.length > 0) {
				events.value += "," + parameters;
			}
		}
	}
}

function toggleVisibility(elementId) {
	if (elementId) {
		var element = document.getElementById(elementId);
		if (element) {
			var style = element.style;
			if (style) {
				if (style.display == 'none') {
					style.display = 'block';
				} else {
					style.display = 'none';
				}
			}
		}
	}
}

/**
 * check whether a given text contains login screen html code
 **/
function isLoginScreen(text) {
	if (text) {
		var pos = text.indexOf("<!-- LoginScreen:Content:Start -->");
		return pos > -1;
	} else {
		return false;
	}
}

/**
 * check whether a given text contains error screen html code
 **/
function isErrorScreen(text) {
	if (text) {
		var pos = text.indexOf("<!-- ErrorScreen:Content:Start -->");
		return pos > -1;
	} else {
		return false;
	}
}

/**
 * check whether a given text contains license error screen html code
 **/
function isLicenseErrorScreen(text) {
	if (text) {
		var pos = text.indexOf("<!-- LicenseErrorScreen:Content:Start -->");
		return pos > -1;
	} else {
		return false;
	}
}

/**
 * extract error information from error screen html code
 **/
function getErrorScreenInfos(text) {
	if (text) {
		var message = '';
		var pos1 = text.indexOf("<!-- ErrorScreen:Title:Start -->");
		var pos2 = text.indexOf("<!-- ErrorScreen:Title:End -->", pos1);
		if (pos1 > -1 && pos2 > pos1) {
			message += text.substring(pos1 + 32, pos2) + '\n';
		}
		pos1 = text.indexOf("<!-- ErrorScreen:URL:Start -->");
		pos2 = text.indexOf("<!-- ErrorScreen:URL:End -->", pos1);
		if (pos1 > -1 && pos2 > pos1) {
			message += text.substring(pos1 + 30, pos2) + '\n';
		}
		pos1 = text.indexOf("<!-- ErrorScreen:Reason:Start -->");
		pos2 = text.indexOf("<!-- ErrorScreen:Reason:End -->", pos1);
		if (pos1 > -1 && pos2 > pos1) {
			message += text.substring(pos1 + 33, pos2) + '\n';
		}
		return message;
	} else {
		return '';
	}
}

/**
 * convert a byte count into a human readable text
 **/
function displaySize(size) {
	if (size < 1024) {
		return size + ' B';
	}
	size = size / 1024;
	if (size < 1024) {
		return (Math.round(size * 10) / 10) + ' KB';
	}
	size = size / 1024;
	return (Math.round(size * 10) / 10) + ' MB';
}

/**
 * convert a milisecond count into a human readable text
 **/
function displayTime(time) {
	time = Math.floor(time / 1000);
	var sec = time % 60;
	time = (time - sec) / 60;
	var min = time % 60;
	var hrs = (time - min) / 60;
	var text = hrs + ':';
	if (min < 10) {
		text = text + '0' + min + ':';
	} else {
		text = text + min + ':';
	}
	if (sec < 10) {
		text = text + '0' + sec;
	} else {
		text = text + sec;
	}
	return text;
}

/*

 var FocusHandler = {

 enabled: true,
 focusElementId: false,
 focusElementName: false,

 registerFocusHandler: function() {
 $(":input").focus(FocusHandler.rememberFocus);
 },

 unregisterFocusHandler: function() {
 $(":input").unbind('focus', FocusHandler.rememberFocus);
 },

 rememberFocus: function() {
 FocusHandler.focusElementId = false;
 FocusHandler.focusElementName = false;
 if (this.id) {
 FocusHandler.focusElementId = this.id;
 }
 if (this.name) {
 FocusHandler.focusElementName = this.name;
 }
 },

 restoreFocus: function() {
 try {
 if (FocusHandler.focusElementId) {
 $("#" + FocusHandler.focusElementId).focus();
 } else if (FocusHandler.focusElementName) {
 // note: name is not escaped (even if it contains special character)
 //       if the name would be escaped, it wouldn't work anymore (at least with JQuery 1.3.1)
 $("[name=" + FocusHandler.focusElementName + "]").focus();
 }
 } catch(ex) {
 // ignore any error
 }
 }

 };

 function escapeJQuerySelector(text) {
 text = text.replace(/\[/g, '\\[');
 text = text.replace(/\]/g, '\\]');
 text = text.replace(/:/g, '\\:');
 text = text.replace(/\./g, '\\.');
 return text;
 }

 */

var AjaxUpdateArea = {

	updateActionTriggered: function(affected_areas, asynchronous_call, jscallbackcode, validationScope) {
		// if no affected_areas are defined, update all areas
		if (!affected_areas) affected_areas = AjaxUpdateArea.findAllUpdateAreas();

		// find workspace form
		var form = AjaxUpdateArea.findWorkspaceForm();
		if (!form) return;

		/*
		 if (form.elements['__controls__']) {
		 form.elements['__controls__'].value = collectControlNames(form);
		 }
		 */

		// find all form values
		var values = AjaxUpdateArea.findValuesInForm(form);

		// make post call
		var url = form.action;
		if (!url || url == '') {
			alert("Workspace form has no Action");
			return;
		}
		AjaxUpdateArea.makeCall(url, values, affected_areas, asynchronous_call, jscallbackcode, validationScope);
	},

	findWorkspaceForm: function() {
		var form = document.forms['workspace'];
		if (!form) {
			if (!workspaceFormWarning) {
				workspaceFormWarning = true;
				alert("Workspace Form not found");
			}
			return;
		}
		return(form);
	},

	findAllUpdateAreas: function() {
		var result = '';
		var areas = AjaxUpdateArea.getElementsByClassName(document.body, 'div', 'AjaxUpdateArea');
		for (var i = 0; i < areas.length; i++) {
			if (!areas[i].id) continue;
			if (result) result += ',';
			result += areas[i].id;
		}
		return(result);
	},

	findValuesInForm: function(form) {
		// find all values in form workspace and return them
		var values = new Object();

		// find all "input" elements in form
		var inputs = form.getElementsByTagName("input");
		for (var i = 0; i < inputs.length; i++) {
			var input = inputs[i];
			if (!input.name) continue;

			// if element is a radio button or checkbox and it isn't selected, the value must not be submitted
			if (input.type.toLowerCase() == 'radio' && !input.checked) continue;
			if (input.type.toLowerCase() == 'checkbox' && !input.checked) continue;

			// if element is a file input field, the value should not be submitted (not supported)
			if (input.type.toLowerCase() == 'file') continue;

			// if element is disabled, value should not be submitted
			if (input.disabled) continue;

			// otherwise, add the value to the list of values
			// there might be multiple elements with the same name. therefore
			// the values of the map 'values' should be arrays.
			AjaxUpdateArea.addValue(values, input.name, input.value);

			if (input.name == '__events__') {
				input.value = '';
			}
		}

		// find all "textarea" elements in form
		var textareas = form.getElementsByTagName("textarea");
		for (var i = 0; i < textareas.length; i++) {
			var textarea = textareas[i];
			if (!textarea.name) continue;
			if (textarea.disabled) continue;
			AjaxUpdateArea.addValue(values, textarea.name, textarea.value);
		}

		// find all "select" elements in form
		var selects = form.getElementsByTagName("select");
		for (var i = 0; i < selects.length; i++) {
			var select = selects[i];
			if (!select.name) continue;
			if (select.disabled) continue;

			// if <select> allows multiple selections ...
			if (select.multiple) {

				// for every option ...
				for (var j = 0; j < select.childNodes.length; j++) {
					var option = select.childNodes[j];
					if (!option.selected) continue;
					if (!option.tagName) continue;
					if (option.tagName.toLowerCase() != 'option') continue;
					if (option.disabled) continue;

					AjaxUpdateArea.addValue(values, select.name, option.value);
				}

			} else {

				// get index of selection option
				var index = select.selectedIndex;
				// if there is a selected option ...
				if (index > -1) {
					var option = select.options[index];
					if (option.disabled) continue;

					AjaxUpdateArea.addValue(values, select.name, option.value);
				}

			}
		}

		return(values);
	},

	addValue: function(values, name, value) {
		if (values[name]) {
			values[name].push(value);
		} else {
			values[name] = [value];
		}
	},

	makeCall: function(url, values, affected_areas, asynchronous_call, jscallbackcode, validationScope) {

		// create post payload
		// append parameter 'ajaxUpdateAreaIds' with a comma separated
		// list of the ids of the AjaxUpdateArea ids
		// example: ajaxUpdateAreaIds=1,2
		var parameterstring = 'ajaxUpdateAreaIds=' + encodeURIComponent(affected_areas);
		if (validationScope) {
			parameterstring += '&validationScope=' + encodeURIComponent(validationScope);
		}
		for (var key in values) {
			for (var i = 0; i < values[key].length; i++) {
				parameterstring += "&";
				parameterstring += encodeURIComponent(key) + "=" + encodeURIComponent(values[key][i]);
			}
		}

		// setup request
		var request = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0");
		if (asynchronous_call) {
			// make the call asynchronously
			request.onreadystatechange = function() {
				if (request.readyState == 4 && request.status == 200) {
					AjaxUpdateArea.handleResult(request);
					if (jscallbackcode) {
						eval(jscallbackcode);
					}
				} else if (request.readyState == 4) {
					AjaxUpdateArea.handleError(request);
				}
			};

			// make call
			request.open('POST', url, true);
			request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			request.setRequestHeader("Content-length", parameterstring.length);
			request.setRequestHeader("Connection", "close");
			request.send(parameterstring);
		} else {
			// make the call synchronously
			request.open('POST', url, false);
			request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			request.setRequestHeader("Content-length", parameterstring.length);
			request.setRequestHeader("Connection", "close");
			request.send(parameterstring);
			AjaxUpdateArea.handleResult(request);
			if (jscallbackcode) {
				eval(jscallbackcode);
			}
		}

	},

	handleResult: function(request) {
		/*
		 typical response:
		 {
		 "1" : "<span class=\"Label\">Hello World<\/span>"
		 "2" : "<img src=\"/nm5/resource/object/Logo/HeadFilter/logo.gif\" alt=\"\" class=\"Image\">",
		 }
		 */

		var text = request.responseText;
		var result;
		try {
			result = eval('(' + text + ')');
		} catch(e) {
			if (isErrorScreen(text)) {
				alert("Ajax Update Area:\nServer Error:\n" + getErrorScreenInfos(text));
			} else if (isLoginScreen(text)) {
				alert("Ajax Update Area:\nAuthentication required");
			} else if (isLicenseErrorScreen(text)) {
				alert("Ajax Update Area:\nLicense Error");
			} else {
				alert("Ajax Update Area:\nCan't evaluate Server Response:\n" + text);
			}
			return;
		}
		var focusElementId = null;
		for (var htmlId in result) {
			if (htmlId == 'screenState' || htmlId == 'screenStateId' || htmlId == 'windowState' || htmlId == 'windowStateId') {
				var form = document.forms['workspace'];
				if (form) {
					var element = form.elements[htmlId];
					if (element) {
						element.value = result[htmlId];
					}
				}
			} else if (htmlId == 'workspace.enctype') {
				var enctype = result[htmlId];
				if (enctype) {
					var form = document.forms['workspace'];
					if (form) {
						form.encoding = enctype;
					}
				}
			} else if (htmlId == 'workspace.focus') {
				var focus = result[htmlId];
				if (focus) {
					focusElementId = focus;
				}
			} else {
				var element = document.getElementById(htmlId);
				if (element) {
					element.innerHTML = result[htmlId];
				}
			}
		}

		if (focusElementId) {
			window.setTimeout(function() {
				focusOnFieldId(focusElementId);
			}, 100);
		}

		/*
		 window.setTimeout(function() {
		 FocusHandler.unregisterFocusHandler();
		 FocusHandler.restoreFocus();
		 FocusHandler.registerFocusHandler();
		 }, 10);
		 */

	},

	handleError: function(request) {
		alert("Ajax Update Area Error:\n" + request.status + " - " + request.statusText);
	},

	getElementsByClassName: function(parent_element, tag_name, class_name) {
		var arrElements = (tag_name == "*" && document.all) ? document.all : parent_element.getElementsByTagName(tag_name);
		var arrReturnElements = new Array();
		class_name = class_name.replace(/\-/g, "\\-");
		var oRegExp = new RegExp("(^|\\s)" + class_name + "(\\s|$)");
		var oElement;
		for (var i = 0; i < arrElements.length; i++) {
			oElement = arrElements[i];
			if (oRegExp.test(oElement.className)) {
				arrReturnElements.push(oElement);
			}
		}
		return (arrReturnElements);
	}

};
