var _ajaxDebug = 0;

var moz = (typeof document.implementation != 'undefined') && (typeof document.implementation.createDocument != 'undefined');
var ie = (typeof window.ActiveXObject != 'undefined'); 

function xml_http_request() { this.init(); };
xml_http_request.prototype = {
	xmlhttp: null,
	xml: null,
	base_url : "index.php?module=xml",
    
	init: function() {
		try {
			this.xmlhttp = new XMLHttpRequest();
		} catch (e) {
			var msxml_xmlhttp_progids = new Array(
					"MSXML2.XMLHTTP.5.0",
					"MSXML2.XMLHTTP.4.0",
					"MSXML2.XMLHTTP.3.0",
					"MSXML2.XMLHTTP",
					"Microsoft.XMLHTTP"
					);
			for (var i = 0; i< msxml_xmlhttp_progids.length; i++) {
				try {
					this.xmlhttp = new ActiveXObject(msxml_xmlhttp_progids[i]);
				} catch (e) { }
			}
		}
	},

	get: function (url) {
		this.xmlhttp.open("GET", this.base_url + "&" + url, false);
		this.xmlhttp.send(null);
		if (this.xmlhttp.readyState == 4 && this.xmlhttp.status == 200) this.xml = this.xmlhttp.responseXML.documentElement;
		else this.xml = null;
		return (this.node2array());
	},

	node2array: function (node) {
		if (node == undefined || node == null) node = this.xml;
		var child_node;
		var has_text = false;
		for (var i = 0; i < node.childNodes.length; i++) {
			var child_node = node.childNodes[i];
			if (child_node.nodeType == 3) has_text = true;
		}
		if (has_text || node.childNodes.length == 0) {
			if (node.hasChildNodes && node.firstChild) value = node.firstChild.nodeValue;
			else value = "";
			return value;
		}
		var result = new Array();
		for (var i = 0; i < node.childNodes.length; i++) {
			var child_node = node.childNodes[i];
			var map = new Object();			
			for (var j = 0; j < child_node.childNodes.length; j++) {
				var sub_child_node = child_node.childNodes[j];
				map[sub_child_node.nodeName] = this.node2array(sub_child_node);
			}
			result[result.length] = map;
		}
		return result;
	}
}

function xsltStore() {this.init();}
xsltStore.prototype = {
	docs:null,
	init:function() {
		this.docs = [];
	},
	get:function(fName) {
		if(!this.docs[fName]) {
			this.load(fName);
		}
		return this.docs[fName];
	},
	load:function(fName) {
		this.docs[fName] = loadXMLByAction("xsltByFileName&fileName="+encodeURIComponent(fName), siteLocation+"common/framework.php");
	}
}

function xmlStore() {this.init();}
xmlStore.prototype = {
	docs:null,
	init:function() {
		this.docs = [];
	},
	get:function(fName) {
		if(!this.docs[fName]) {
			this.load(fName);
		}
		return this.docs[fName];
	},
	load:function(fName) {
		this.docs[fName] = loadXMLByAction("xmlByFileName&fileName="+encodeURIComponent(fName), siteLocation+"common/framework.php");
	}
}

function xmlObj() { this.init(); };
xmlObj.prototype = {
	doc:null,
	init:function() {
		if (moz) {
			this.doc = document.implementation.createDocument("", "", null)
			this.doc.async = false;
		} else if (ie) {
			this.doc = new ActiveXObject("Microsoft.XMLDOM");
			this.doc.async = false;
			while(this.doc.readyState != 4) {};
		}
	}
}
// check for XPath implementation
if( document.implementation.hasFeature("XPath", "3.0") )
{
   // prototying the XMLDocument
   XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
   {
      if( !xNode ) { xNode = this; } 
      var oNSResolver = this.createNSResolver(this.documentElement)
      var aItems = this.evaluate(cXPathString, xNode, oNSResolver, 
                   XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
      var aResult = [];
      for( var i = 0; i < aItems.snapshotLength; i++)
      {
         aResult[i] =  aItems.snapshotItem(i);
      }
      return aResult;
   }

   // prototying the Element
   Element.prototype.selectNodes = function(cXPathString)
   {
      if(this.ownerDocument.selectNodes)
      {
	     return this.ownerDocument.selectNodes(cXPathString, this);
      }
      else{throw "For XML Elements Only";}
   }
}
// check for XPath implementation
if( document.implementation.hasFeature("XPath", "3.0") )
{
   // prototying the XMLDocument
   XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
   {
      if( !xNode ) { xNode = this; } 
      var xItems = this.selectNodes(cXPathString, xNode);
      if( xItems.length > 0 )
      {
         return xItems[0];
      }
      else
      {
         return null;
      }
   }
   
   // prototying the Element
   Element.prototype.selectSingleNode = function(cXPathString)
   {	
      if(this.ownerDocument.selectSingleNode)
      {
         return this.ownerDocument.selectSingleNode(cXPathString, this);
      }
      else{throw "For XML Elements Only";}
   }
}

function xslt_transform(xmlSource, xsltSource, _container) {
	var params=false;
	var debug = false;
	if(xslt_transform.arguments.length>3) {
		params=arguments[3];
	}
	if(xslt_transform.arguments.length>4) {
		debug=arguments[4];
	}
	if(ie) {
		var xsl=null;
		var template=null;
		var processor=null;

		xsl = new ActiveXObject("MSXML2.FreeThreadedDomDocument.3.0");
		xsl.async = false;
		xsl.loadXML(xsltSource.xml);

		template = new ActiveXObject("MSXML2.XSLTemplate")
		template.stylesheet = xsl;
		processor = template.createProcessor();

		processor.input = xmlSource;

		if(params) {
			for(key in params) {
				if(typeof(params[key])!="function") {
					processor.addParameter(key, params[key])
				}
			}
		}
		processor.transform();
		if(debug) {alert(processor.output);}
		_container.innerHTML=processor.output;//xmlSource.transformNode(xsltSource);
	} else if(moz) {
		var result;
		var xsltProcessor = new XSLTProcessor();
		xsltProcessor.importStylesheet(xsltSource);

		if(params) {
			for(key in params) {
				xsltProcessor.setParameter(null, key, params[key])
			}
		}

		result = xsltProcessor.transformToFragment(xmlSource, document);
		_container.innerHTML="";
		_container.appendChild(result);
	} else {
		alert("Your browser still not supported yet");
	}
}

function get_request(f) {
	var r=new String("");
	var j=0;
	var curEl=null;
	for(var i=0;i<f.elements.length;i++) {
		curEl=f.elements[i];
		if(curEl.name!="") {
			r+=(j>0?"&":"")+curEl.name+"="+(curEl.type=="checkbox"?(curEl.checked?"checked":"unchecked"):curEl.value);
			j++;
		}
	}
	return r;
}

function update_node(node, value) {
	var txt=null;
	if(!node.hasChildNodes()) {
		txt=document.createTextNode("");
		node.appendChild(txt);
	}
	node.firstChild.nodeValue=value;

}

function empty_node(node) {
	while(node.hasChildNodes()) {
		node.removeChild(node.firstChild);
	}
}

function string2xml(string) {
	var xml;
	if (document.all) {
		xml = new ActiveXObject("Msxml2.DOMDocument.3.0");
		xml.loadXML(string);
	} else {
		var dom_parser = new DOMParser();
		xml = dom_parser.parseFromString(string, "application/xml");
	}
	return xml;
}

function xml2string(xml) {
	if (xml == null || xml == undefined) {
		return null;
	}
	if (document.all) {
		return xml.xml;
	} else {
		try {
			return (new XMLSerializer()).serializeToString(xml);
		} catch (e) {
			return false;
		}
	}
}

function form2string(f) {
	var res = new String("");
	var arr = new Array();
	var e = null;
	var j = 0;
	for(var i=0;i<f.elements.length;i++) {
		e = f.elements[i];
		if((e.name!='')&&(!((e.type=="checkbox"||e.type=="radio")&&!e.checked))) {
			if(e.nodeName == "SELECT") {
				for(var o=0;o<e.options.length;o++) {
					if(e.options[o].selected) {
						arr[j] = encodeURIComponent(e.name)+"="+encodeURIComponent(e.options[o].value);
						j++;                                                                   
					}
				}
			} else {
				arr[j] = encodeURIComponent(e.name)+"="+encodeURIComponent(e.value);
			}
			j++;
		}
	}
	for(var i=0;i<arr.length;i++) {
		res += (i!=0 ? "&" : "")+arr[i];
	}
	return res;
}

function form2xmlstring(f) {
	var res = new String("");
	var arr = new Array();
	var e = null;
	var j = 0;
	for(var i=0;i<f.elements.length;i++) {
		e = f.elements[i];
		if(e.name!='') {
			arr[j] = "<"+e.name+">"+(e.type=="checkbox" ? (e.checked ? "1" : "0") : e.value)+"</"+e.name+">";
			j++;
		}
	}
	res = "<item>\n";
	for(var i=0;i<arr.length;i++) {
		res += arr[i]+"\n";
	}
	res += "</item>\n"
	return res;
}

function loadXMLByAction(a) {
	var script = (loadXMLByAction.arguments.length>1) ? arguments[1] : scriptName;
	var sendAction = (a=="") ? null : "action="+a;
	if(!loadXMLByAction.hr) {loadXMLByAction.hr = new xml_http_request();}
	loadXMLByAction.hr.xmlhttp.open("POST", script, false, "", "");
	loadXMLByAction.hr.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	loadXMLByAction.hr.xmlhttp.send(sendAction);
	if(_ajaxDebug) {
		alert(script+"\n"+a+"\n"+loadXMLByAction.hr.xmlhttp.responseText);
	}
	return loadXMLByAction.hr.xmlhttp.responseXML;
}

function loadTextByAction(a) {
	var script = (loadTextByAction.arguments.length>1) ? arguments[1] : scriptName;
	var sendAction = (a=="") ? null : "action="+a;
	if(!loadTextByAction.hr) {loadTextByAction.hr = new xml_http_request();}
	loadTextByAction.hr.xmlhttp.open("POST", script, false, "", "");
	loadTextByAction.hr.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	loadTextByAction.hr.xmlhttp.send(sendAction);
	return loadTextByAction.hr.xmlhttp.responseText;
}

function xmlLoader() { this.init(); };
xmlLoader.prototype = {
	objects: null,
    onloadstart: null,
    onloadend: null,
	cache:null,

	_c:0,

	_nextResponseIndex:0,

	init: function() {
		this.objects = [];
		this.cache = [];
		this._nextResponseIndex = 0;
	},

	free: function() {
		for(var i in this.objects) {
			delete this.objects[i];
		}
		this.objects = [];
	},

	add: function(url, action) {
		var i = this.objects.length;
		var cache = arguments[2] ? arguments[2] : false;
		var contentType = arguments[3] ? arguments[3] : "xml";				
		this.objects.push({url:url, action:action, xhr:new xml_http_request(), response:null, cache:cache, contentType:contentType, callback: function(){ stateChanged(i);}});
	},

	view: function() {
		for(var i=0;i<this.objects.length;i++) {
			alert(this.objects[i].url+" "+this.objects[i].action+" "+this.objects[i].xhr);
		}
	},

	load: function() {
		this._nextResponseIndex = 0;
		
		currentLoader = this;
		if(this.onloadstart) {
			this.onloadstart.call();
		}
		this._c = this.objects.length;			
				
		if(this._c<=0) {			
			if(this.onloadend) {
				this.onloadend.call();
			}
		}

		for(var i = 0; i < this.objects.length; i++) {			
			if(this.objects[i].cache == true && this.cache[this.objects[i].url+"++"+this.objects[i].action]) {
				this.objects[i].response = this.cache[this.objects[i].url+"++"+this.objects[i].action];
				this._c--;				
				if(this._c <= 0) {					
					if(this.onloadend) {
						this.onloadend.call();
					}
				}
			} else {				
				this.objects[i].xhr.xmlhttp.open("POST", this.objects[i].url, true, "", "");				
				this.objects[i].xhr.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');				
				this.objects[i].xhr.xmlhttp.onreadystatechange = this.objects[i].callback;
				this.objects[i].xhr.xmlhttp.send(this.objects[i].action);
			}
		}
	},
	
	getNextResponse: function() {
		var res = null;
		var mode = arguments[0] ? arguments[0] : "xml";
		switch(mode) {
			case "xml":
				res = this.objects[this._nextResponseIndex].response;
				break;
			default:
				res = this.objects[this._nextResponseIndex].responseText;
				break;
		}
		this._nextResponseIndex++;
		return res;
	}
}

function stateChanged(idx) {
	if(currentLoader.objects[idx].xhr.xmlhttp.readyState==4 && currentLoader.objects[idx].xhr.xmlhttp.status==200) {		
		if(_ajaxDebug) {
			alert(currentLoader.objects[idx].url+"\n"+currentLoader.objects[idx].action+"\n"+currentLoader.objects[idx].xhr.xmlhttp.responseText);
		}
		currentLoader.objects[idx].response = currentLoader.objects[idx].xhr.xmlhttp.responseXML;
		currentLoader.objects[idx].responseText = currentLoader.objects[idx].xhr.xmlhttp.responseText;
		
		switch(currentLoader.objects[idx].contentType) {
			case "json":
				eval(currentLoader.objects[idx].responseText);
				break;
			case "xml":
			default:
				break;
		}
		//alert("XMLLoader Queue Size : "+currentLoader._c+" "+currentLoader.onloadend);		
		currentLoader._c--;				
		
		if(currentLoader.objects[idx].cache) {
			currentLoader.cache[currentLoader.objects[idx].url+"++"+currentLoader.objects[idx].action] = currentLoader.objects[idx].response; 
		}
		if(currentLoader._c <= 0) {			
			if(currentLoader.onloadend) {
				currentLoader.onloadend.call();
			}
		}
	}
}

var httpRequest = new xml_http_request();
var xmlLoader = new xmlLoader();
var xsltStore = new xsltStore();
var xmlStore = new xmlStore();
