// NimaSystems LTD - Plovdiv
// http://www.nimasystems.com
// +   original by: Yordan Lazarov and Martin Kovachev

if (typeof DOMParser == "undefined") {
	DOMParser = function() {
	}
	DOMParser.prototype.parseFromString = function(str, contentType) {
		if (typeof (ActiveXObject) != 'undefined') {

			var xmldata = new ActiveXObject('MSXML2.DomDocument');
			xmldata.async = false;
			xmldata.loadXML(str);
			return xmldata;
		} else if (typeof (XMLHttpRequest) != 'undefined') {
			var xmldata = new XMLHttpRequest;
			if (!contentType) {
				contentType = 'application/xml';
			}
			xmldata.open('GET', 'data:' + contentType + ';charset=utf-8,'
					+ encodeURIComponent(str), false);
			if (xmldata.overrideMimeType) {
				xmldata.overrideMimeType(contentType);
			}
			xmldata.send(null);
			return xmldata.responseXML;
		}
	}
}

var Utils = {

	fillSelect : function(items, html_obj) {
		$e(html_obj).length = 0;

		if (items.length > 0) {
			for (i = 0; i < items.length; i++) {

				var elem = items[i];
				var id = elem.attributes.getNamedItem("id").nodeValue;
				var name = elem.childNodes[0].nodeValue;

				$e(html_obj)[i] = new Option(name, id, (i == 0 ? true : false));

			}
		}

	}

}

var ajaxRPC = {
	__form_object :new Object,
	__forms_data :new Array(),
	__loading_message :'<span class="loading">loading....</span>',
	__message_timeout :2000,
	__message_fadeopacity :90,
	__message_hideform :0,
	__redirect :1,
	__ajaxRPCLoaded :0,
	handler_uri: '',
	htmlspecialchars : function(encodedHtml) {
		encodedHtml = escape(encodedHtml);
		encodedHtml = encodedHtml.replace(/\//g, "%2F");
		encodedHtml = encodedHtml.replace(/\?/g, "%3F");
		encodedHtml = encodedHtml.replace(/=/g, "%3D");
		encodedHtml = encodedHtml.replace(/&/g, "%26");
		encodedHtml = encodedHtml.replace(/@/g, "%40");
		
		return encodedHtml;
	},
	getElementsByTagNames : function(list, obj) {
		if (!obj)
			var obj = document;
		var tagNames = list.split(',');
		var resultArray = new Array();
		for ( var i = 0; i < tagNames.length; i++) {
			var tags = obj.getElementsByTagName(tagNames[i]);
			for ( var j = 0; j < tags.length; j++) {
				resultArray.push(tags[j]);
			}
		}
		var testNode = resultArray[0];
		if (testNode.sourceIndex) {
			resultArray.sort( function(a, b) {
				return a.sourceIndex - b.sourceIndex;
			});
		} else if (testNode.compareDocumentPosition) {
			resultArray.sort( function(a, b) {
				return 3 - (a.compareDocumentPosition(b) & 6);
			});
		}
		return resultArray;
	},
	array_keys : function(input, search_value, strict) {
		var tmp_arr = new Array(), strict = !!strict, include = true, cnt = 0;

		for (key in input) {
			include = true;
			if (search_value != undefined) {
				if (strict && input[key] !== search_value) {
					include = false;
				} else if (input[key] != search_value) {
					include = false;
				}
			}

			if (include) {
				tmp_arr[cnt] = key;
				cnt++;
			}
		}

		return tmp_arr;
	},

	inArray : function(needle, haystack, strict) {

		var found = false, key, strict = !!strict;

		for (key in haystack) {
			if ((strict && haystack[key] === needle)
					|| (!strict && haystack[key] == needle)) {
				found = true;
				break;
			}
		}

		return found;
	},
	eventMessageFade : function(message_id, opac, dont_remove) {
		var passed = parseInt(opac);
		var newOpac = parseInt(passed + 10);
		if (newOpac < ajaxRPC.__message_fadeopacity) {
			$e(message_id).style.opacity = '.' + newOpac;
			$e(message_id).style.filter = "alpha(opacity:" + newOpac + ")";
			opacityID = window.setTimeout("ajaxRPC.eventMessageFade('"
					+ message_id + "', '" + newOpac + "')", 20);
		} else {
			if ($e(message_id) != undefined) {
				// $e(message_id).style.opacity =
				// '.'+(ajaxRPC.__message_fadeopacity/100);
				// $e(message_id).style.filter =
				// "alpha(opacity:"+ajaxRPC.__message_fadeopacity+")";
				if (!parseInt(ajaxRPC.__message_hideform)) {

					removeID = window.setTimeout("ajaxRPC.eventMessageRemove('"
							+ message_id + "', "
							+ ajaxRPC.__message_fadeopacity + ")",
							ajaxRPC.__message_timeout);
				} else {
					$e(message_id).nextSibling.style.visibility = 'hidden';
				}
			}
		}
	},
	eventMessageRemove : function(message_id, opac) {
		var passed = parseInt(opac);
		var newOpac = parseInt(passed - 10);
		if (newOpac > 0) {
			$e(message_id).style.opacity = '.' + newOpac;
			$e(message_id).style.filter = "alpha(opacity:" + newOpac + ")";
			opacityID = window.setTimeout("ajaxRPC.eventMessageRemove('"
					+ message_id + "', '" + newOpac + "')", 20);
		} else {
			$e(message_id).parentNode.removeChild($e(message_id));
			ajaxRPC.__redirect = 1;
		}
	},
	// exec javascript script
	execScript : function(script) {
		if (script) {
			// alert(script);
			var execute = function() {
				eval(script);
			}
			execute.onerror = alert;
			execute();

		}
	},
	redirectURL : function(url) {

		if (!ajaxRPC.__redirect) {
			setTimeout("ajaxRPC.redirectURL('" + url + "')", 10);
			return false;
		}
		if (url) {
			location.href = url;
		}
	},
	showEventMessage : function(form_obj, formMessage, dont_remove) {
		if (form_obj != undefined && formMessage.length) {
			var message_id = "eventmsg_" + form_obj.getAttribute('name');
			if ($e(message_id) == undefined) {

				var msgObject = document.createElement('div');
				msgObject.innerHTML = formMessage;
				msgObject.className = 'eventFormRequired';
				msgObject.style.position = 'absolute';
				msgObject.style.width = form_obj.offsetWidth + "px";
				msgObject.style.height = form_obj.offsetHeight + "px";
				msgObject.style.backgroundColor = '#ffffff';
				msgObject.style.opacity = '.0';
				msgObject.style.filter = "alpha(opacity:0)";
				msgObject.style.zIndex = 999;
				msgObject.setAttribute("id", message_id)
				form_obj.parentNode.insertBefore(msgObject, form_obj);
				ajaxRPC.eventMessageFade(message_id, 10, dont_remove);
			}
		}
	},

	getElementDomObj : function(obj, element_id, field) {
		if (obj[element_id] != undefined) {

			if (obj[element_id].getElementsByTagName(field)[0].childNodes.length) {
				return obj[element_id].getElementsByTagName(field)[0].firstChild.nodeValue;
			}
			// return
			// obj[element_id].getElementsByTagName(field)[0].firstChild.nodeValue;
		}
	},
	validateFields : function(form_obj, xmlDoc) {

		formname = form_obj.getAttribute('name');

		var globalError = 0;

		var interator = (new DOMParser()).parseFromString(xmlDoc, "text/xml");

		// GET METADATA
		var metadata = interator.getElementsByTagName('metadata');
		if (this.getElementDomObj(metadata, 0, 'globalmessage'))
			var globalMessage = this.getElementDomObj(metadata, 0,
					'globalmessage');
		else
			var globalMessage = "";
		if (this.getElementDomObj(metadata, 0, 'result'))
			var globalResult = parseInt(this.getElementDomObj(metadata, 0,
					'result'));
		else
			var globalResult = "";
		if (this.getElementDomObj(metadata, 0, 'javascriptfunc'))
			var globalScript = this.getElementDomObj(metadata, 0,
					'javascriptfunc');
		else
			var globalScript = "";
		if (this.getElementDomObj(metadata, 0, 'redirecturl'))
			var globalRedirect = this.getElementDomObj(metadata, 0,
					'redirecturl');
		else
			var globalRedirect = "";
		if (this.getElementDomObj(metadata, 0, 'exectimeout'))
			var globalTimeout = this.getElementDomObj(metadata, 0,
					'exectimeout');
		else
			var globalTimeout = "";
		if (this.getElementDomObj(metadata, 0, 'fadeopacity'))
			var globalFadeOpacity = this.getElementDomObj(metadata, 0,
					'fadeopacity');
		else
			var globalFadeOpacity = "";
		if (this.getElementDomObj(metadata, 0, 'hideform'))
			var globalHideForm = this.getElementDomObj(metadata, 0, 'hideform');
		else
			var globalHideForm = "";

		if (globalTimeout.length)
			ajaxRPC.__message_timeout = globalTimeout * 1000;
		if (globalFadeOpacity.length)
			ajaxRPC.__message_fadeopacity = globalFadeOpacity
		if (globalHideForm.length)
			ajaxRPC.__message_hideform = globalHideForm
			// alert(globalTimeout);
			// GET FIELDS
		var elements = new Array();
		
		var fields_root = interator.getElementsByTagName('field');
		if ((!fields_root.length) && (!globalScript) && (!globalRedirect)) {
			globalError++;
		}
		for (i = 0; i < fields_root.length; i++) {
			// alert(root[i].getElementsByTagName("msg").length);
			var field_name = fields_root[i].getElementsByTagName("name")[0].firstChild.nodeValue;
			if (this.getElementDomObj(fields_root, i, 'msg'))
				var field_msg = this.getElementDomObj(fields_root, i, 'msg');
			else
				var field_msg = '';
			if (this.getElementDomObj(fields_root, i, 'value'))
				var field_value = this
						.getElementDomObj(fields_root, i, 'value');
			else
				var field_value = '';
			// alert(field_valid);
			elements[field_name] = new Array();
			elements[field_name][0] = field_msg;
			elements[field_name][1] = field_value;

			// alert(field_name);
		}
		
		// SHOW ERROR LOG IF HAVE ERROR
		if (globalError) {
			// alert(globalError);
			ajaxRPC.__message_hideform = 1;
			ajaxRPC.showEventMessage(form_obj, (xmlDoc));
			return false;
		}
		var elementsNames = ajaxRPC.array_keys(elements);
		var inputs = ajaxRPC.getElementsByTagNames('input,select,textarea',
				form_obj);
		// var selects = form_obj.getElementsByTagName('select');
		// inputs += selects;

		var error = 0;
		for (i = 0; i < inputs.length; i++) {

			var input_name = inputs[i].getAttribute('name');
			if (ajaxRPC.inArray(input_name, elementsNames)) {
				// set field value
				inputs[i].value = elements[input_name][1];

				var requiredMsg_id = "req_" + input_name + "_" + formname + "_"
						+ i
				if (elements[input_name][0].length) {
					// inputs[i].className = "requiredField";
					inputs[i].style.backgroundColor = "#f0f0f0";
					if ($e(requiredMsg_id) == undefined) {
						var requiredMsg = document.createElement('div');
						requiredMsg.innerHTML = elements[input_name][0];
						requiredMsg.setAttribute("id", requiredMsg_id);
						requiredMsg.className = "requiredMsg";
						inputs[i].parentNode.insertBefore(requiredMsg,
								inputs[i].nextSibling);
					} else {
						$e(requiredMsg_id).innerHTML = elements[input_name][0];
					}
					error++;
					// inputs[i].appendChild(requiredMsg);
					// alert(elements[input_name][1]);
				} else {
					// inputs[i].className = "inputField";
					inputs[i].style.backgroundColor = "";
					if ($e(requiredMsg_id) != undefined) {
						inputs[i].parentNode.removeChild($e(requiredMsg_id));
					}
				}

			}
			// enable submit buttons
			if (inputs[i].getAttribute('type') == 'submit')
				inputs[i].disabled = false;
		}

		if (globalResult) {
			if (globalMessage.length) {
				ajaxRPC.showEventMessage(form_obj, globalMessage);
			}
			if (globalScript.length) {
				ajaxRPC.execScript(globalScript);
			}
		} else {
			if (globalMessage.length) {
				ajaxRPC.__redirect = 0;
				ajaxRPC.showEventMessage(form_obj, globalMessage);
			}
			if (globalScript.length) {
				ajaxRPC.execScript(globalScript);
			}
			if (globalRedirect.length) {
				ajaxRPC.redirectURL(globalRedirect);
				globalResult = 1;
			}
		}

		if (globalResult || error) {
			return false;
		} else {
			ajaxRPC.showEventMessage(form_obj, new Array(
					ajaxRPC.__loading_message));
			form_obj.submit();
		}

	},
	createAjaxObject : function() {
		var http_request = false;

		try {
			http_request = new XMLHttpRequest;
			if (http_request.overrideMimeType) {
				http_request.overrideMimeType('text/xml');
			}

		} catch (e) {
			var msxml = [ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP',
					'Microsoft.XMLHTTP' ];
			for ( var i = 0, len = msxml.length; i < len; ++i) {
				try {
					http_request = new ActiveXObject(msxml[i]);

					break;
				} catch (e) {
				}
			}
		}

		if (!http_request) {
			return false;
		}
		return http_request;
	},
	showOverlay : function() {
		if ($e('overlay') == undefined) {
			var overlay = document.createElement('div');
			overlay.setAttribute('id', 'overlay');
			overlay.className = 'overlay';
			document.body.appendChild(overlay);
		}

	},
	hideOverlay : function() {
		if ($e('overlay') != undefined) {
			// alert('close');
			$e('overlay').parentNode.removeChild(document
					.getElementById('overlay'))
		}

	},
	formRequest : function(form_obj) {
		this.showOverlay();
		var parameters = ajaxRPC.getFormParams(form_obj);

		var http_request = ajaxRPC.createAjaxObject();

		ajaxRPC.__form_object = form_obj;

		http_request.onreadystatechange = function() {
			// alert(formobject);

			if (http_request.readyState == 4) {
				if (http_request.status == 200) {

					result = http_request.responseText;
			
					debugmessage = (new DOMParser()).parseFromString(result,
							"text/xml");
					debugmessage1 = debugmessage
							.getElementsByTagName('metadata');
					debugmessage2 = ajaxRPC.getElementDomObj(debugmessage1, 0,
							'debug');

					if (debugmessage2) {
						$e('debug').innerHTML = '<br /><div style="border: 1px solid gray; padding: 3px;">' + debugmessage2 + '</div>';
					}

					// ################
					var browser = navigator.appName.toLowerCase();
					var rawresult = debugmessage.getElementsByTagName('rawresult');
							

					if (rawresult.length == 1) {
						if (browser == 'microsoft internet explorer') {
							var raw_dom_obj = rawresult[0].firstChild;
						} else {
							var raw_dom_obj = rawresult[0].childNodes[1];
						}

						var func = raw_dom_obj.nodeName;
						var html_obj = raw_dom_obj.attributes
								.getNamedItem("id").nodeValue;

						switch (func) {
						case 'fillSelect':

							var items = (raw_dom_obj
									.getElementsByTagName('item'));

							Utils.fillSelect(items, html_obj);

							break;
						default:

							break;

						}

					}

					// #################

					ajaxRPC.validateFields(ajaxRPC.__form_object, result);
					ajaxRPC.hideOverlay();
				} else {
					ajaxRPC.hideOverlay();
					if ($e('showdebug'))
						alert('There was a problem with the request.');
					else
						return;
				}

			}
		}
		// alert(parameters);
		// return false;
		
		http_request.open('POST', this.handler_uri, true);
		http_request.setRequestHeader("Content-Type",
				"application/x-www-form-urlencoded;charset=utf-8");
		http_request.setRequestHeader("Content-Length", parameters.length);
		http_request.setRequestHeader("Connection", "close");
		http_request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
		http_request.setRequestHeader("CacheControl", "no-cache");
		http_request.setRequestHeader("Pragma", "no-cache");
		http_request.setRequestHeader("Expires", -1);
		http_request.send(parameters);
		return false;
	},
	init : function(handler_uri, current_controller) {
		ajaxRPC.__form_object = new Object();
		
		ajaxRPC.handler_uri = handler_uri;
		
		var html_forms = document.getElementsByTagName('form');

		for (f = 0; f < html_forms.length; f++) {
			var class_name = html_forms[f].className;
			if (class_name != undefined) {
				if (class_name.indexOf("req") != -1) {

					html_forms[f].onsubmit = function() {
						ajaxRPC.formRequest(this);
					}
				}
			}
		}

		// write rpc form
		ajaxRPC.__initAJAXRPC_Form();

		// write flash layer
		document.write('<div id="flash_message"></div>');
	},
	setFormFieldName : function(form_name, field, value) {

		if (ajaxRPC.__forms_data[form_name] == undefined) {
			ajaxRPC.__forms_data[form_name] = new Array();
		}
		ajaxRPC.__forms_data[form_name][field] = value;
	},
	getFormParams : function(obj) {
		var formname = obj.getAttribute('name');
		var inputs = ajaxRPC
				.getElementsByTagNames('input,select,textarea', obj);

		var params = new Array();
		var params_strings = new Array();
		for (i = 0; i < inputs.length; i++) {

			if (inputs[i].getAttribute('type') == 'checkbox') {
				if (!inputs[i].checked) // inputs[i].value = 0; else
										// inputs[i].value=1;
				{
					continue;
				}
			}
			if (inputs[i].getAttribute('type') == 'radio') {
				if (!inputs[i].checked)
					continue;
			}

			param_key = inputs[i].getAttribute('name');

			if (inputs[i].nodeName.toLowerCase() == 'select') {

				if (inputs[i].multiple) {
					var tmp_val = new Array();
					for (k = 0; k < inputs[i].options.length; k++) {
						if (inputs[i].options[k].selected == true) {
							tmp_val[tmp_val.length] = inputs[i].options[k].value
						}
					}
					param_val = tmp_val.join(',');

				} else {
					if (inputs[i].selectedIndex != -1) {
						field_value = inputs[i].options[inputs[i].selectedIndex].value;
					}
					param_val = field_value;
				}
			} else {
				param_val = inputs[i].value;
			}

			param_val = param_val.replace(/\+/gi, '%2B');

			params[param_key] = param_val;
			params_strings[i] = param_key + "=" + param_val;

			// set form field info

			// disable submit buttons
			if (inputs[i].getAttribute('type') == 'submit')
				inputs[i].disabled = true;

		}

		return params_strings.join("&") + "&__ajaxrpc_formname__=" + formname
				+ "&__ajaxrpc_url__=" + escape(location.href);
	},
	ajaxFlash : function(message, timeout) {
		f1 = document.getElementById('flash_message');

		f1.innerHTML = message;
		f1.style.display = 'block';

		window.setTimeout("ajaxRPC.hideFlash()", timeout);
	},
	hideFlash : function() {
		f1 = document.getElementById('flash_message');
		f1.style.display = 'none';
	},
	createInputField : function(type, name, value) {
		var field = document.createElement('input');

		field.setAttribute('type', type);
		field.setAttribute('name', name);
		field.setAttribute('value', value);

		return field;
	},
	__initAJAXRPC_Form : function() {
		document
				.write('<form id="__ajaxrpc_form__" name="__ajaxrpc_form__" action="/" class="req" method="post">'
						+ '<input type="hidden" name="__ajaxrpc_type__" value="" />'
						+ '<input type="hidden" name="__ajaxrpc_route__" value="" />'
						+ '<input type="hidden" name="__ajaxrpc_params__" value="" />'
						+ '<input type="hidden" name="__ajaxrpc_callback_func__" value="" />'
						+ '</form>');

		var f = document.__ajaxrpc_form__;
		f.onsubmit = function() {
			ajaxRPC.formRequest(f)
		};
		ajaxRPC.__ajaxRPCLoaded = 1;
	},
	__internalCall : function(route, calltype, params, callback_func) {

		if (ajaxRPC.__ajaxRPCLoaded != 1) {
			ajaxRPC.__initAJAXRPC_Form();

		}

		var f = eval('document.__ajaxrpc_form__');

		f.__ajaxrpc_route__.value = route;
		f.__ajaxrpc_params__.value = params;
		f.__ajaxrpc_type__.value = calltype;
		f.__ajaxrpc_callback_func__.value = callback_func;

		formSubmit('__ajaxrpc_form__');
	},
	call : function(route, calltype, params, callback_func) {
		ajaxRPC.__internalCall(route, 'rpc', new Array(), '');
	},
	rpc : function(route) {
		ajaxRPC.__internalCall(route, 'rpc', new Array(), '');
	},
	validate : function(form_name) {
		var obj = eval("document." + form_name);

		obj.appendChild(ajaxRPC.createInputField('hidden', '__ajaxrpc_type__',
				'form_validator'));
		obj.appendChild(ajaxRPC.createInputField('hidden', '__ajaxrpc_route__',
				obj.action));
		obj.appendChild(ajaxRPC.createInputField('hidden',
				'__ajaxrpc_params__', new Array(form_name)));
		obj.appendChild(ajaxRPC.createInputField('hidden',
				'__ajaxrpc_callback_func__', ''));
		
		formSubmit(form_name);
	}
}