isys.namespace("ajax");

isys.ajax.connect = function() {

};

isys.ajax.m_isysConnectionPool = [];
isys.ajax.m_isysConnectionCount = 0;

isys.ajax.isysGetConnection = function() {
    var retVal = null;
    for (var i = 0; i < isys.ajax.m_isysConnectionPool.length; i++) {
        if (isys.ajax.m_isysConnectionPool[i]) {
            retVal = isys.ajax.m_isysConnectionPool[i];
            isys.ajax.m_isysConnectionPool[i] = null;
            isys.ajax.m_isysConnectionCount--;
            break;
        }
    }
    return retVal;
};
    
isys.ajax.isysReleaseConnection = function(c) {
    isys.ajax.m_isysConnectionCount++;
    for (var i = 0; i < isys.ajax.m_isysConnectionPool.length; i++) 
        if (!isys.ajax.m_isysConnectionPool[i]) {
            isys.ajax.m_isysConnectionPool[i] = c;
            return;
        }
    isys.ajax.m_isysConnectionPool[isys.ajax.m_isysConnectionPool.length] = c;
};

isys.ajax.dynamicLoad = function(conn) {
	if (conn.statusCode() == 200) {
		var x = conn.getXML();
		var c = x.documentElement.firstChild;
		while (c) {
			if (c.nodeType == 1) {
				var e = document.getElementById("ajaxSection" + c.getAttribute("id"));
				if (e)
					e.innerHTML = (c.textContent || c.text);
			}
			c = c.nextSibling;
		}
		var refresh = conn.getResponseHeader("isys-refresh");
		if (refresh != null && refresh != "")
			window.setTimeout(prepareISYSAjax, 1500);
	}
};

isys.ajax.connect.prototype = {
	m_conn: null,
	context: null,
	callback: null,

	makeConnection: function() {
		var retVal = isys.ajax.isysGetConnection();
		if (retVal == null) {
	        try {
		        retVal = new XMLHttpRequest();
	        } catch(e) {
		        msxml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
		        for (var i = 0; i < msxml.length; i++) {
			        try {
				        retVal = new ActiveXObject(msxml[i]);
			        } catch(e) {
			        }
		        }			
	        }
	    }
		return retVal;
	},
	
	__doRelease: function() {
	    isys.ajax.isysReleaseConnection(this.m_conn);
	},
	
	open: function(method, url, sync) {
		this.m_conn = this.makeConnection();
		if (!this.m_conn)
			return false;
		if (typeof(sync) == "undefined") sync = false;

		this.m_conn.open(method, url, !sync);

		var me = this;
		this.m_conn.onreadystatechange = function() {
			if (me.m_conn.readyState == 4) {
				if(me.callback) me.callback(me);
				me.__doRelease();
			}
		};
		return this.m_conn != null;	
	},
	
	send: function(body) {
        this.m_conn.send(body);
		return this.m_conn != null;	
	},
	
	asyncRequest: function(method, url, body, callback) {
		this.callback = callback;
	    this.open(method, url);
		return this.send(body);
	},
	
	statusCode: function() {
		if (this.m_conn)
			return this.m_conn.status;
		else
			return null;
	},
	
	getXML: function() {
		if (this.m_conn)
			return this.m_conn.responseXML;
		else
			return null
	},
	
	getText: function() {
		if (this.m_conn)
			return this.m_conn.responseText;
		else
			return null;
	},
	
	contentType: function() {
		return this.getResponseHeader("Content-Type");
	},
	
	getContext: function() {
		return this.context;
	},
	
	getResponseHeader: function(name) {
		if (this.m_conn)
			return this.m_conn.getResponseHeader(name);
		else
			return null;	
	},
	
	setRequestHeader: function(name, value) {
	    this.m_conn.setRequestHeader(name, value);
	},
	
	getAllResponseHeaders: function() {
        if (this.m_conn)
			return this.m_conn.getAllResponseHeaders();
		else
			return null;		
	},
	
	abort: function() {
		if (this.m_conn)
			this.m_conn.abort();
	}
};

isys.ajax.call = function(url, svr, func, params) {
    this.url = url;
    this.server = svr;
    this.func = func;
    this.params = params;
    this.callback = null;
};

isys.ajax.call.prototype = {
    callback: null, 
    conn: null,
    inerror: false,
    error: null,
    
    handleCallback: function(conn) {
        var me = conn.context;
        if (me.callback) {
			try {
				if (me.debug)
					alert(conn.getText());
				me.callback(me, me.deserialize(conn.getXML().documentElement));
			} catch(e) {
				me.inerror = true;
				me.error = e;
				me.callback(me, "isys.ajax.error: " + e);
			}
        };
    },
    
    execute: function(sync) {
        var req = "<r object=\"" + this.server + "\" function=\"" + this.func + "\">";
        for (var i = 0; i < this.params.length; i++) {
            req += this.serialize(this.params[i], "p");
        }
        req += "</r>";
        
        var conn = new isys.ajax.connect();
        conn.context = this;
        conn.callback = this.handleCallback;
        conn.open("POST", this.url, sync);
        conn.setRequestHeader("Content-Type", "text/xml");
        conn.send(req);
        this.conn = conn;
        
        if (sync)
            return this.deserialize(conn.getXML().documentElement);// getAllResponseHeaders();
    },
    
    abort: function() {
        this.conn.abort();
    },
    
    deserialize: function(xml) {
        var n = xml;
        switch (n.getAttribute("type")) {
            case "numeric":
                return parseFloat(this.nodeValue(n));
            case "boolean":
				return this.nodeValue(n) != 0;
            case "date":
                return new Date(this.nodeValue(n));
            case "error":
                throw this.nodeValue(n) //+ " [line: " + n.getAttribute("line") + "]";
            case "array":
                return this.deserializeArray(n);
            case "dataset":
                var retVal = this.deserializeArray(n);
                for (var i = 0; i < n.attributes.length; i++) {
                    retVal[n.attributes[i].name] = n.attributes[i].value;
                }
                return retVal;
            case "object":
                return this.deserializeObject(n);
            case "xml":
                return n.firstChild;
            default:
                return this.nodeValue(n);
        }
    },
    
    deserializeArray: function(xml) {
        var n = xml.firstChild;
        var retVal = [];
        while (n != null) {
            if (n.nodeType == 1 && n.nodeName == "a")
                retVal[retVal.length] = this.deserialize(n);
            n = n.nextSibling;
        }
        return retVal;
    },
    
    deserializeObject: function(xml) {
        var retVal = [];
        var n = xml.firstChild;
        while (n != null) {
            if (n.nodeName == "p")
                retVal[n.getAttribute("name")] = this.nodeValue(n);
            n = n.nextSibling;
        }
        return retVal;
    },
    
    nodeValue: function(n) {
        var retVal = "";
        n = n.firstChild;
        while (n != null) {
            if (n.nodeType == 3)
                retVal += n.nodeValue;
            n = n.nextSibling;
        }
        return retVal;
    },
    
    serialize: function(p, t, k) {
    	function encode(v) {
			var div = document.createElement('div');
			var text = document.createTextNode(v);
			div.appendChild(text);
			return div.innerHTML;
		}
        typ = typeof(p);
        if (typ == "object" && typeof(p.getFullYear) != "undefined") 
            typ = "date";
        else if (typ == "object" && typeof(p.length) != "undefined" && p.length) 
            typ = "array";
    
        var retVal = "<" + t + " type=\"" + typ + "\"" + (k?" key=\"" + k + "\"":"") + ">";
        if (typeof(p) == "object") {
            if (typeof(p.getFullYear) != "undefined") {
                retVal += p.toUTCString();
            } else if (typeof(p.length) != "undefined") {
                if (p.length)
                    for (var i = 0; i < p.length; i++) 
                        retVal += this.serialize(p[i], "a", i);
                else
                    for (var k in p) 
                        retVal += this.serialize(p[k], "a", k);
            }
        } else
            retVal += encode(p);
        retVal += "</" + t + ">";        
        return retVal;
    }
};