﻿
function XML(){}

XML.Logger = []

/* XML.Cache object */


XML.Cache = {}

XML.unloadTemplate = function(template) {

	if(XML.Cache[template]) {

		if(breakFilepath(template).extension == 'js') {
			var scriptNode = XML.Cache[template].node;
			scriptNode.parentNode.removeChild(scriptNode);
		}
		
		delete XML.Cache[template];
	}
}

/*
    XML.DefaultPacket class
*/

XML.DefaultPacket = function(module, action){
    return {type:'request', query:{module:module, action:action}, xmldata:{}}
}

/* XML.Template class */

XML.Template = function(callback){
    this.callback = callback
}

XML.Template.prototype.load = function(template, url, module, action){
    var req = new XML.Request(this.onLoad.bind(this), this.onError.bind(this))
    var doc = new XML.Document('packet', XML.DefaultPacket(module, action))
    doc.packet.query.tmpl= template

    req.send(url, doc)
}

/* callback function. Returns last loaded template */

XML.Template.prototype.onLoad = function(response){
    var packet = response.packet
    XML.Cache[packet.query.tmpl] = new XML.Document('xsl:stylesheet', packet.xmldata['xsl:stylesheet'])
    if(this.callback) this.callback()
}

XML.Template.prototype.onError = function(response){
    alert('Response is not valid XML')    
}


/*
    XML.Document class
*/

XML.Document = function(xmlnode, object){	
    switch(typeof(xmlnode)){
        case "object":
            this.document = xmlnode
            this.rootNode = xmlnode.documentElement.nodeName
            this[this.rootNode] = this.__parseXML()
        break
        case "string":
            this[xmlnode] = object
            this.rootNode = xmlnode
			
            this.document = this.__buildDocument()
        break
    }
}


/*
    Serialize this[this.rootNode]
    object to XML string
*/

XML.Document.prototype.serialize = function(root, object) {
    var node = this.__buildDocument(root, object)
    if (typeof XMLSerializer != "undefined")
        return (new XMLSerializer()).serializeToString(node);
    else if (node.xml) return node.xml;
}

/*
    return valid domxml object with content-type text/xml
*/

XML.Document.prototype.XML = function(root, object) {
    if(typeof DOMParser != "undefined"){
        var document = new DOMParser()
        return document.parseFromString(this.serialize(root, object), 'text/xml')
    }
    else {
        var document = new ActiveXObject("MSXML.DomDocument")
        document.loadXML(this.serialize(root, object))
        return document
    }
}

/* 
    apply xsl template to xml data
*/

XML.Document.prototype.transform = function(xmldoc){
    var xml = xmldoc.XML()
    if (typeof XSLTProcessor != "undefined") {
        var proc = new XSLTProcessor(); proc.importStylesheet(this.XML())
        var div = _('div'); div.appendChild(proc.transformToFragment(xml, document))
        return div.innerHTML
    } else return xml.transformNode(this.XML())
}

/*
    return XMLDcument without contentType object from
    this[this.rootNode] object 
*/

XML.Document.prototype.__buildDocument = function(root, object) {
    if(!object) object = this[this.rootNode]
    if(!root) root = this.rootNode
    var document = this.__create()
    var node = this.__parseObject(document, root, object)
    document.appendChild(node)
    return document
}

/*
    create new XMLDocument object
*/

XML.Document.prototype.__create = function(){
    if (document.implementation && document.implementation.createDocument)
        return document.implementation.createDocument("", "", null)
    else return new ActiveXObject("Microsoft.XMLDOM")
}



/*
    parse this[this.rootNode] 
    object to XML Node
*/


XML.Document.prototype.__parseObject = function(document, root, obj){    
    var node = _(root, document)
    if(obj instanceof Object){
        for(var i in obj){
            if(typeof(obj[i])=='object' && !obj[i].length){
                node.appendChild(this.__parseObject(document, i, obj[i]))
            }
            if(typeof(obj[i])=='object' && obj[i].length){
                for(var j=0; j<obj[i].length; j++){
                    node.appendChild(this.__parseObject(document, i, obj[i][j]))
                }
            }
            if(typeof(obj[i]) == 'string'){
				if(i!='cdata') node.setAttribute(i, unescape(obj[i]))
                else {					
				/*	 var str = [[/\&/g,'&#38;'],
								['"','&#34;'],
								['<','&#60;'],								
								['>','&#62;'],								
								['ù','&#xF9;'],
								['à','&#xE0;'],
								['ç','&#xE7;'],
								['è','&#xE8;'],
								['é','&#xE9;'],
								['à','&#224;'],];				
					 
					 var tmp = obj[i];
					 var out='',pos=0;
					 for(var j=0;j<str.length;j++){
						  while(tmp.indexOf(str[j][0]) != -1){
							  pos  = tmp.indexOf(str[j][0])+1;
							  out += tmp.substr(0,pos).replace(str[j][0],str[j][1])
  							  tmp  = tmp.substr(pos,tmp.length - pos);	
						  }						  
					  }	
					  out += tmp
 					  obj[i] = out;
//					obj[i] = escape(obj[i])*///					
					//obj[i] = unescape(obj[i]);	
				//	obj[i] = obj[i].replace(/\&/g, "&#38;")
					node.appendChild(document.createTextNode(obj[i]))
				}
            }
        }
    }
    return node
}

/*
    parse XMLDocument object to 
    this[this.rootNode] object
*/


XML.Document.prototype.__parseXML = function ( node ) {
    if(!node) node = this.document.documentElement
    if ( node.nodeType == 3 || node.nodeType == 4 ) return node.nodeValue;
    var struct = {'cdata':''}; var nodeCount = {};
    
    if ( node.attributes && node.attributes.length ) {
        for ( var i=0; i<node.attributes.length; i++ ) {
            struct[node.attributes[i].nodeName] = node.attributes[i].nodeValue
        }
    }
    
    if ( node.childNodes && node.childNodes.length ) {
        for (var i=0; i<node.childNodes.length; i++ ) {
            var type = node.childNodes[i].nodeType;
            if ( type != 3 && type != 4 ){
                var key = node.childNodes[i].nodeName;
                if (value = this.__parseXML(node.childNodes[i])){
                    if (!nodeCount[key]) nodeCount[key] = 0; nodeCount[key]++;
                    if (nodeCount[key] == 1) struct[key] = value
                    else if ( nodeCount[key] == 2) struct[key] = [struct[key], value]
                    else struct[key].push(value)
                }
            } else  struct['cdata'] += node.childNodes[i].nodeValue
        }		
    } 	
	return struct;
}

/*
    XML.Request object
*/

XML.Request = function(onLoad, onError){
    this.request = this.__create()
    this.onError = onError; 
    this.onLoad = onLoad
    this.request.onreadystatechange = this.__receive.bind(this);   
}

XML.Request.prototype.__create = function(){
	if (window.XMLHttpRequest) return new XMLHttpRequest();
    else if (window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP");
	
}

XML.Request.prototype.__receive = function(){
    if ( this.request.readyState == 4 ){
    	try{
	        if( this.request.status == 200 ) {
    	        if(this.onLoad) { 
					
        	    	if(this.request.responseText.substr(0,17) == '_(Error in query)'){
						application.error(10001,this.request.responseText);
					}
					if(this.request.getResponseHeader("Content-Type") != 'text/xml') 
       					alert(this.request.responseText); 
						
 					XML.Logger.push( new XML.Document(this.request.responseXML) )
                	this.onLoad( new XML.Document(this.request.responseXML) ) }
	        } else if(this.onError) this.onError(this.request.status)
    	} catch(e){}
	}
}




XML.Request.prototype.send = function(url, packet){	
	XML.Logger.push(packet)
	var xml = packet.serialize()
	this.request.open('POST', url, true);
    this.request.setRequestHeader("Content-Type", "text/xml")
    this.request.send(xml);
}

XML.Request.prototype.post = function(url, packet){
	XML.Logger.push(packet)
    var xml = packet.serialize()
    this.request.open('POST', url, true);
    this.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    this.request.send(xml);
    
}




