/* namespacing object */
var net = new Object();

var debugAjax = false;


net.READY_STATE_UNINITIALIZED = 0;
net.READY_STATE_LOADING = 1;
net.READY_STATE_LOADED = 2;
net.READY_STATE_INTERACTIVE = 3;
net.READY_STATE_COMPLETE = 4;


/*--- content loader object for cross-browser requests ---*/
net.ContentLoader = function(url, onload, onerror, method, params, contentType) {
    this.req = null;
    this.onload = onload;
    this.onerror = (onerror) ? onerror : this.defaultError;
    this.loadXMLDoc(url, method, params, contentType);
}

net.ContentLoader.prototype = {
    loadXMLDoc: function(url, method, params, contentType) {
        if (!method) {
            method = "GET";
        }
        if (!contentType && method == "POST") {
            contentType = 'application/x-www-form-urlencoded';
        }
        if (window.XMLHttpRequest) {
            this.req = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            this.req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        if (this.req) {
            try {
                var loader = this;
                this.req.onreadystatechange = function() {
                    loader.onReadyState.call(loader);
                }
                this.req.open(method, url, true);
                if (contentType) {
                    this.req.setRequestHeader('Content-Type', contentType);
                }
                if (debugAjax) {
                    alert(params);
                }
                this.req.send(params);
            } catch (err) {
                this.onerror.call(this);
            }
        }
    },

    onReadyState: function() {
        var req = this.req;
        var ready = req.readyState;
        if (ready == net.READY_STATE_COMPLETE) {
            var httpStatus = req.status;
            if (httpStatus == 200 || httpStatus == 0) {
                this.onload.call(this);
            } else {
                this.onerror.call(this);
            }
        }
    },

    defaultError: function() {
        alert("error fetching data!"
    + "\n\nreadyState:" + this.req.readyState
    + "\nstatus: " + this.req.status
    + "\nheaders: " + this.req.getAllResponseHeaders());
    }
}




net.cmdQueues = new Array();
net.Base;

net.CommandQueue = function(url, freq) {
    net.Base = this;
    this.id = "1";
    net.cmdQueues["1"] = this;
    this.url = url;
    this.queued = new Array();
    this.sent = new Array();
    this.queryStringVariables = new Hashtable();
    if (freq) {
        this.repeat(freq);
    }
}

net.CommandQueue.STATUS_QUEUED = -1;
net.CommandQueue.STATE_UNINITIALIZED = net.READY_STATE_UNINITIALIZED;
net.CommandQueue.STATE_LOADING = net.READY_STATE_LOADING;
net.CommandQueue.STATE_LOADED = net.READY_STATE_LOADED;
net.CommandQueue.STATE_INTERACTIVE = net.READY_STATE_INTERACTIVE;
net.CommandQueue.STATE_COMPLETE = net.READY_STATE_COMPLETE;
net.CommandQueue.STATE_PROCESSED = 5;

net.CommandQueue.PRIORITY_NORMAL = 0;
net.CommandQueue.PRIORITY_IMMEDIATE = 1;

net.CommandQueue.TYPE_MULTIPROCESS = 0;
net.CommandQueue.TYPE_SINGLEPROCESS = 1;
net.CommandQueue.TYPE_SINGLEPROCESS_HOLDQAUEUE = 2;

net.CommandQueue.holdQueue = false;


net.CommandQueue.prototype = {
    addCommand: function(command) {
        if (this.isCommand(command)) {
            if (debugAjax) {
                alert("isCommand");
            }
            var added = false;
            if (command.type == net.CommandQueue.TYPE_SINGLEPROCESS || command.type == net.CommandQueue.TYPE_SINGLEPROCESS_HOLDQAUEUE) {
                if (debugAjax) { alert("Single Process Command"); }
                for (var i = 0; i < this.queued.length; i++) {
                    if (this.queued[i].ajaxCommand == command.ajaxCommand) {
                        this.queued[i] = command;
                        if (debugAjax) { alert("Single Process Command UPDATED"); }
                        added = true;
                        break;
                    }
                }
            }
            if (!added) {
                this.queued.append(command, true);
                if (debugAjax) { alert("added command"); }
            }
            if (command.priority == net.CommandQueue.PRIORITY_IMMEDIATE) {
                if (debugAjax) { alert("PRIORITY_IMMEDIATE"); }
                this.fireRequest();
            }
        } else {
            if (debugAjax) {
                alert("not command");
            }
        }
    },

    fireRequest: function() {
        var data = "";
        var commandStr = 'ajaxCommand=';

        if (this.holdQueue || this.queued.length == 0) {
            return;
        }
        var newQueued = new Array();
        for (var i = 0; i < this.queued.length; i++) {
            var cmd = this.queued[i];
            if (this.isCommand(cmd)) {
                var processCommand = true;
                if (cmd.type == net.CommandQueue.TYPE_SINGLEPROCESS || cmd.type == net.CommandQueue.TYPE_SINGLEPROCESS_HOLDQAUEUE) {
                    for (var j = 0; j < this.sent.length; j++) {
                        if (this.sent[j] && this.sent[j].ajaxCommand == cmd.ajaxCommand) {
                            newQueued.append(cmd);
                            processCommand = false;
                            break;
                        }
                    }
                }
                if (processCommand) {
                    if (cmd.tpe == net.CommandQueue.TYPE_SINGLEPROCESS_HOLDQAUEUE) {
                        this.holdQueue = true;
                    }
                    if (i > 0) {
                        commandStr += ",";
                    }
                    var commandIdentifier = cmd.ajaxCommand + "~" + cmd.id;
                    commandStr += commandIdentifier;
                    this.addCommandVariablesToQueryStringVariables(commandIdentifier, cmd.QueryStringVariables());
                    this.sent[cmd.id] = cmd;
                }
            }
        }
        if (commandStr.length > 12) { //12 is because "ajaxcommand=" see line 153 above
            data = commandStr + this.buildQueryStringVariables();
            if (debugAjax) {
                alert("Query string = " + data);
            }
            this.loader = new net.ContentLoader(this.url, net.CommandQueue.onload, net.CommandQueue.onerror, "POST", data);
        }
        this.queued = newQueued;
        this.queryStringVariables = new Hashtable();
    },

    addCommandVariablesToQueryStringVariables: function(commandIdentifier, commandVariables) {
        commandVariables.moveFirst();
        while (commandVariables.next()) {
            this.queryStringVariables.put(commandIdentifier + commandVariables.getKey(), escape(commandVariables.getValue()).replace(/\+/g, "%2B"));
        }
        return
    },

    buildQueryStringVariables: function() {
        var returnValue = "";
        this.queryStringVariables.moveFirst();
        while (this.queryStringVariables.next()) {
            returnValue += "&" + this.queryStringVariables.getKey() + "=" + this.queryStringVariables.getValue();
        }
        return returnValue;
    },

    isCommand: function(obj) {
        return (
    this.implementsProp(obj, "id")
    && this.implementsProp(obj, "priority")
    && this.implementsFunc(obj, "QueryStringVariables")
    && this.implementsFunc(obj, "ParseResponse")
    && this.implementsProp(obj, "type")
  );
    },

    repeat: function(freq) {
        this.unrepeat();
        if (freq > 0) {
            this.freq = freq;
            var cmd = "net.Base.fireRequest()";
            this.repeater = setInterval(cmd, freq * 1000);
        }
    },

    unrepeat: function() {
        if (this.repeater) {
            clearInterval(this.repeater);
        }
        this.repeater = null;
    },

    implementsProp: function(obj, propertyName) {
        return (obj[propertyName] != null);
    },

    implementsFunc: function(obj, funcName) {
        return (obj[funcName] != null); /*&& this[funcName] instanceof Function;*/
    },

    HoldQueue: function() {
        this.holdQueue = true;
    },

    ReleaseQueue: function() {
        this.holdQueue = false;
        for (var i = 0; i < this.queued.length; i++) {
            if (this.queued[i].priority == net.CommandQueue.PRIORITY_IMMEDIATE) {
                net.Base.fireRequest();
                return;
            }
        }
    }
}

net.CommandQueue.onload = function() {
    if (debugAjax) {
        alert("OnLoad");
    }
    var xmlDoc = this.req.responseXML;
    var myText = this.req.responseText;
    var elDocRoot = xmlDoc.getElementsByTagName("commands")[0];
    if (elDocRoot) {
        if (debugAjax) {
            alert("Good XML");
        }
        var needFireQueue = false;
        for (var i = 0; i < elDocRoot.childNodes.length; i++) {
            elChild = elDocRoot.childNodes[i];
            if (elChild.nodeName == "command") {
                var attrs = elChild.attributes;
                var id = attrs.getNamedItem("id").value;
                var cmdName = attrs.getNamedItem("cmdName").value;
                //Get refence from myself here
                if (debugAjax) {
                    alert(id);
                }
                command = net.Base.sent[id];
                if (command) {
                    if (debugAjax) {
                        alert("GotCommand");
                    }
                    var unhandledException = elChild.attributes.getNamedItem("unhandledException");
                    if (unhandledException && unhandledException.value == 'true') {
                        alert(DecodeText(elChild.attributes.getNamedItem("message").value));
                    } else {
                        command.ParseResponse(elChild);
                        document.getElementById("AJAXStatus").innerHTML = "<input type=\"hidden\" id=\"" + cmdName + "_complete\"";
                        if (!needFireQueue && command.type == net.CommandQueue.TYPE_SINGLEPROCESS && command.priority == net.CommandQueue.PRIORITY_IMMEDIATE) {
                            for (var j = 0; j < net.Base.queued.length; j++) {
                                if (command.ajaxCommand == net.Base.queued[j].ajaxCommand) {
                                    needFireQueue = true;
                                    break;
                                }
                            }
                        }
                        net.Base.sent[id] = null;
                    }
                }
            }
            if (needFireQueue) {
                net.Base.fireRequest();
            }
        }
    }
}

net.CommandQueue.onerror = function() {
    alert("problem sending the data to the server");
}

function DecodeText(text) {
    return unescape(text.replace(/\+/g, ' '));
}





