// Обект за заявките през Ajax
// Идеята е да не се изпълнява повече от 1 заявка от клиент
function xmlAjax() {
	this.status		= 0; // Статус на обекта 0 - Idle, 1 - Изпращане на заявка, 2 - Изпълнение на функция след края на заявката
	
	this.requests 	= Array(); // Масив с текущите заявки
	this.debug		= false; // false - без дебъг, true - с дебъг
	this.noAJAX		= false;
	
	this.reset = function () {
		// Рестартира обекта, като изтрива всички заявки
		// Изтриваме текущото състояние на обекта
		this.status		= 0;
		this.requests 	= Array();
		//this.cache		= Object();
		this.noAJAX		= zXmlHttp ? false : true;
	}
	
	this.loadJsonRequest = function (url, json_var_name, ok_func, error_func) { 
		// Функция за зареждане на заявка
		var index = this.requests.length;
		this.requests[index] = new Object();
		
		this.requests[index].type = 'GET'; // Тип на заявката POST, GET
		this.requests[index].url = url; // URL на заявката
		this.requests[index].ok_function = ok_func; // Функция която се изпълнява при header "Result: OK"
		this.requests[index].error_function = error_func; // Функция която се изпълнява при header "Result: ERROR"
		this.requests[index].json_var_name = json_var_name; // Име на променливата в която да се вкара рейултата от JSON
	}
	
	this.loadJsonRequestAndExecute = function (url, json_var_name, ok_func, error_func) {
		this.loadJsonRequest(url, json_var_name, ok_func, error_func);
		this.executeRequests();
	}
	
	this.loadGetRequest = function (url, ok_func, error_func, is_cacheable) { 
		// Функция за зареждане на заявка
		var index = this.requests.length;
		this.requests[index] = new Object();
		
		this.requests[index].type = 'GET'; // Тип на заявката POST, GET
		this.requests[index].url = url; // URL на заявката
		this.requests[index].ok_function = ok_func; // Функция която се изпълнява при header "Result: OK"
		this.requests[index].error_function = error_func; // Функция която се изпълнява при header "Result: ERROR"
		//if (is_cacheable)	this.requests[index].is_cacheable = true;
		
	}
	
	this.loadGetRequestAndExecute = function (url, ok_func, error_func) {
		this.loadGetRequest(url, ok_func, error_func);
		this.executeRequests();
	}
	
	this.loadPostRequest = function (form, button, ok_func, error_func) { 
		// Функция за зареждане на заявка
		var index = this.requests.length;
		this.requests[index] = new Object();
		
		this.requests[index] = new Object();
		this.requests[index].type = 'POST'; // Тип на заявката POST, GET
		this.requests[index].form = form; // Референс към формат
		this.requests[index].button = button; // Референс към натиснатия бутон, ако е натиснат
		this.requests[index].ok_function = ok_func; // Функция която се изпълнява при header "Result: OK"
		this.requests[index].error_function = error_func; // Функция която се изпълнява при header "Result: ERROR"
	}
	
	this.loadPostRequestAndExecute = function (form, button, ok_func, error_func) {
		//alert(form+', '+button+', '+ok_func+', '+error_func);
		this.loadPostRequest(form, button, ok_func, error_func);
		this.executeRequests();
	}
	
	this.changeForms = function() {
		var forms = document.all ? document.forms : document.getElementsByTagName('form');
		var oThis = this;
		
		for(var i=0; i<forms.length; i++) {
			// Ако на формата е зададен метод `ajax` или `ajax_xml` й се сменя onclick на submit бутоните
			method = forms[i].getAttribute('method');
			
			if (method) method = method.toLowerCase();
			
			if (method == 'ajax' || method == 'ajax_xml') {
				var parts = forms[i].action.split('@');
				
				// Оправяме action-a след като сме взели ok_func и error_func
				forms[i].action = parts[0];
				
				if (parts[1]) 
					forms[i].ok_func = parts[1];
				else if (typeof(forms[i].ok_func) == 'undefined')
					forms[i].ok_func = null;
				
				if (parts[2])
					forms[i].error_func = parts[2];
				else if (typeof(forms[i].error_func) == 'undefined')
					forms[i].error_func = null;
				
				if (!forms[i].onsubmit)
					forms[i].onsubmit = function () {return false;};
					
				for(var j=0; j<forms[i].elements.length; j++) {
					var have_submit_btn = false;
					// Поставяме на субмит бутоните onclick, щото javascript e прост и не работи през onsubmit
					if (forms[i].elements[j].type == 'submit') {
						have_submit_btn = true;
						var el = forms[i].elements[j];
						
						if (el.onclick && typeof(el.onclick_old) == 'undefined')
							el.onclick_old = el.onclick;
						
                        forms[i].elements[j].onclick = 
							function (event) {
                                if (event==undefined) event= window.event;
								var srcElement;
								if (event.target)
									srcElement = event.target;
								else if (event.srcElement) 
									srcElement = event.srcElement;
								
								if (srcElement.onclick_old && srcElement.onclick && (srcElement.onclick_old.valueOf().toString() !== srcElement.onclick.valueOf().toString())) {
									if (srcElement.onclick_old() === false) return false;
								}
								
								oThis.loadPostRequestAndExecute(srcElement.form, srcElement, srcElement.form.ok_func, srcElement.form.error_func);
							}
					}
				}
				
				forms[i].submit = function () {
					oThis.loadPostRequestAndExecute(this, null, this.ok_func, this.error_func);
					return false;
				}
			}
		}
	}
	
	this.xmlJsonRequest = function (url, json_var_name, ok_func, error_func) {
		// Функцоия за GET заявки
		var oThis = this;
		
		var oXmlHttp = zXmlHttp.createRequest(); // Обекта на zXmlHttp, който ще се използва за заявките
		oXmlHttp.open("get", url+'&random='+Math.random(), true);
		eval(json_var_name+'=null');
		oXmlHttp.onreadystatechange = function () {
			if (oXmlHttp.readyState == 4) {
				if (oXmlHttp.getAllResponseHeaders)
					var res = oXmlHttp.getAllResponseHeaders();
				else 
					res = '';
				
				var result = 'OK';
				var return_res = true;
				
				if (res.indexOf("Result") >= 0) var result = oXmlHttp.getResponseHeader("Result");
				
				if (oThis.debug === true){
					var debug_window = window.open('','Debugging','config=text, width=1000, height=500, resizable=no, scrollbars=yes')
					debug_window.document.write("<pre>"+oXmlHttp.responseText.htmlEntities()+"</pre>");
				}
				
				eval(json_var_name+'='+'Array()');
				if (oXmlHttp.responseText != '') {
					eval(json_var_name+'='+'(' + oXmlHttp.responseText + ')');
				}
				
				oThis.status = 2; // Слагаме статус за изпълнение на функците след заявката
				if (result == 'ERROR') {
					if (error_func) eval(decodeURIComponent(error_func));
					return_res = false;
				}
				
				if (result == 'OK' || result == null) {
					if (ok_func) eval(decodeURIComponent(ok_func));
				}
				
				// Нулираме статуса
				oThis.status = 0;
				oThis.executeRequests();
				
				return return_res;
			}
		}
		oXmlHttp.send(null);
	}
	
	this.xmlGetRequest = function (url, ok_func, error_func) {
		// Функцоия за GET заявки
		var oThis = this;
		
		var oXmlHttp = zXmlHttp.createRequest(); // Обекта на zXmlHttp, който ще се използва за заявките
		oXmlHttp.open("get", url+'&random='+Math.random(), true);
		oXmlHttp.onreadystatechange = function () {
			if (oXmlHttp.readyState == 4) {
				if (oXmlHttp.getAllResponseHeaders)
					var res = oXmlHttp.getAllResponseHeaders();
				else 
					res = '';
				
				var result = 'OK';
				var return_res = true;
				
				if (res.indexOf("Result") >= 0) var result = oXmlHttp.getResponseHeader("Result");
				
				if (oThis.debug === true){
					var debug_window = window.open('','Debugging','config=text, width=1000, height=500, resizable=no, scrollbars=yes')
					debug_window.document.write("<pre>"+oXmlHttp.responseText.htmlEntities()+"</pre>");
				}
				
				if (oXmlHttp.responseText != '') {
					var tempString = oXmlHttp.responseText;
					var tempNode = zXmlDom.createDocument();
                    
					tempNode.loadXML(tempString);
					
					var tap_exploder = false;
					if (tempString.indexOf('<div id="multy_parser">') >= 0) {
						// Ще се парсват много резултати
						tempNode = tempNode.childNodes[0].childNodes;
					} else {
						tempNode = tempNode.childNodes;
						if (document.all) tap_exploder = true;
					}
					
					for (var i = 0; i < tempNode.length; i++){
                        document.external_scripts = null;
                        document.external_scripts = new Array();
                        
						checkNode = tempNode[i];
						if (checkNode.nodeType != document.ELEMENT_NODE) checkNode = checkNode.nextSibling;
						
						targetid = null;
						if (checkNode) {
							targetid = checkNode.getAttribute('id');
							// Да му го .... ма малоумния Exploder
							is_select = checkNode.tagName == 'optgroup' || checkNode.tagName == 'select';
						}
						
						if (targetid && (targetid != '')) {
							var targetobject = $(targetid);
								newNode = checkNode;
							
							if (tap_exploder === true) {
								$(targetid).outerHTML = tempString;
								importedNode = document._importNode(newNode, true, 0);
								if (document.external_scripts) {
									for(var j in document.external_scripts) eval(document.external_scripts[j]);
								}
							} else {
								if (newNode.nodeType != document.ELEMENT_NODE) newNode = newNode.nextSibling;
								if (newNode) {
									importedNode = document._importNode(newNode, true, 0);
									if (targetobject) {
										/*if (!oThis.cache[url]) oThis.cache[url] = Object();
										oThis.cache[url].content = importedNode;
										oThis.cache[url].ok_function = ok_func;
										oThis.cache[url].error_function = error_func;
										oThis.cache[url].status = result;*/
										
										targetobjectParent = document.getElementById(targetid).parentNode;
										targetobjectParent.insertBefore(importedNode, targetobject);
										targetobjectParent.removeChild(targetobject);
										if (!document.importNode && !is_select) {
											$(targetid).outerHTML = $(targetid).outerHTML;
										}
									}
									if (document.external_scripts) {
										//oThis.cache[url].ext_scripts = document.external_scripts;
										for(var j in document.external_scripts) {
											//alert(document.external_scripts[j]);
											eval(document.external_scripts[j]);
										}
									}
								}
							}
						}
					}
					oThis.changeForms();
				}
				
				oThis.status = 2; // Слагаме статус за изпълнение на функците след заявката
				if (result == 'ERROR') {
					if (error_func) eval(decodeURIComponent(error_func));
					return_res = false;
				}
				
				if (result == 'OK' || result == null) {
					if (ok_func) eval(decodeURIComponent(ok_func));
				}
				
				// Нулираме статуса
				oThis.status = 0;
				oThis.executeRequests();
				
				return return_res;
			}
		}
		oXmlHttp.send(null);
	}
	
	this.xmlPostRequest = function (oForm, button, ok_func, error_func) { // oForm - референс към формата, button - натиснатия бутон, ...
		if (!oForm) return false;
		
		if (typeof(oForm.onsubmit) != 'undefined') oForm.onsubmit();
		
		var oThis = this;
		var sBody = getRequestBody(oForm, button);
		
		var oXmlHttp = zXmlHttp.createRequest(); // Обекта на zXmlHttp, който ще се използва за заявките
		
		oXmlHttp.open("post", oForm.action+'&random='+Math.random(), true);
		oXmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		oXmlHttp.setRequestHeader("Accept-Charset", "UTF-8; q=1");
		
		oXmlHttp.onreadystatechange = function () {
			if (oXmlHttp.readyState == 4) {
				var res = oXmlHttp.getAllResponseHeaders();
				var result = 'OK';
				var return_res = true;
				
				if (res.indexOf("Result") >= 0) var result = oXmlHttp.getResponseHeader("Result");
				
				if (oThis.debug === true) {
					var debug_window = window.open('','Debugging','config=text, width=1000, height=500, resizable=no, scrollbars=yes')
					debug_window.document.write("<pre>"+oXmlHttp.responseText.htmlEntities()+"</pre>");
				}
				
				var tempString = oXmlHttp.responseText;
				var tempNode = zXmlDom.createDocument();
				
				if (tempString.length > 0) {
					tempNode.loadXML(tempString);
					
					var tap_exploder = false;
					if (tempString.indexOf('<div id="multy_parser">') >= 0) {
						// Ще се парсват много резултати
						tempNode = tempNode.childNodes[0].childNodes;
					} else {
						tempNode = tempNode.childNodes;
						if (document.all) tap_exploder = true;
					}
					
					
					for (var i = 0; i < tempNode.length; i++){
                        document.external_scripts = null;
                        document.external_scripts = new Array();
                        
						checkNode = tempNode[i];
						if (checkNode.nodeType != document.ELEMENT_NODE) checkNode = checkNode.nextSibling;
						
						targetid = null;
						if (checkNode) {
							targetid = checkNode.getAttribute('id');
							// Да му го .... ма малоумния Exploder
							is_select = checkNode.tagName == 'optgroup' || checkNode.tagName == 'select';
						}
						
						if (targetid && (targetid != '')) {
							var targetobject = document.getElementById(targetid);
								newNode = checkNode;
							
							if (tap_exploder === true) {
								$(targetid).outerHTML = tempString;
								importedNode = document._importNode(newNode, true, 0);
								if (document.external_scripts) {
									for(var j in document.external_scripts) eval(document.external_scripts[j]);
								}
							} else {
								if (newNode.nodeType != document.ELEMENT_NODE) newNode = newNode.nextSibling;
								if (newNode) {
									importedNode = document._importNode(newNode, true, 0);
									
									if (targetobject) {
										targetobjectParent = document.getElementById(targetid).parentNode;
										targetobjectParent.insertBefore(importedNode, targetobject);
										targetobjectParent.removeChild(targetobject);
										if (!document.importNode && !is_select) {
											$(targetid).outerHTML = $(targetid).outerHTML;
										}
									}
									if (document.external_scripts) {
										for(var j in document.external_scripts) eval(document.external_scripts[j]);
									}
								}
							}
							
						}
					}
					
					oThis.changeForms();
				}
				
				
				oThis.status = 2; // Слагаме статус за изпълнение на функците след заявката
				if (result == 'ERROR') {
					if (error_func) eval(decodeURIComponent(error_func));
					var return_res = false;
				}
				
				if (result == 'OK' || result == null) {
					if (ok_func) {
						eval(decodeURIComponent(ok_func));
					}
				}
				
				// Нулираме статуса
				oThis.status = 0;
				oThis.executeRequests();
				
				return return_res;
			}
		}
		oXmlHttp.send(sBody);
		
		return false;
	}
	
	this.executeRequests = function () {
		// Функция която "завърта" заявките в момента и ги изпълнява
		if (this.status == 0 && this.requests.length > 0) {
			// В момента не се изпълняват заявки и има чакащи такива
			var query = this.requests.shift(); // Взима първата заявка в масива със заявките
			
			this.status = 1; // Слагаме статус за изпълнение на заявката
			
			if (query && typeof(query.type) != 'undefined') {
				switch (query.type) {
					case 'GET':
						if (query.json_var_name)
							this.xmlJsonRequest(query.url, query.json_var_name, query.ok_function, query.error_function);
						else 
							this.xmlGetRequest(query.url, query.ok_function, query.error_function);
					break;
					
					case 'POST':
						this.xmlPostRequest(query.form, query.button, query.ok_function, query.error_function);
					break;
				}
			}
		}
	}
	
	this.reset();
}

var AjaxRequests = new xmlAjax; // Обекта който ще се ползва за заявките
var json_global = null;