window.Connection = window.Connection || {
    // A counter for transactions
    TransactionCounter: -1,    
    
    // An array of active request objects
    ActiveTransactions: new Array(),
    
    // Wraps a new XMLHttpRequest object with other properties
    GetRequest: function () {
        var xhr = this.GetXmlHttpRequestObject();
        if (xhr) {
            this.TransactionCounter++;
            var request = {
                            
                ID:this.TransactionCounter, // A unique, consecutive ID
                
                PollID:undefined,           // The ID to be assigned by setInterval, 
                                            //   probably session-unique but not guaranteed
                                            
                TimeOut:1000,               // Time out in milliseconds                            
                                            
                XHR:xhr                    // The XMLHttpRequest object
                
            };
            
            // Add request reference to array
            this.ActiveTransactions.push(request);
            
            return request;
        }
        return null;
    },
    
    SendRequest: function(url, callback) {
        var request = this.GetRequest();
        if (request) {
            var pollInterval = 50;  // Check every 50 ms for completion
            var pollID = window.setInterval(
			        function(){
				        if(request.XHR.readyState == 4){
	                        if(request.XHR.status !== undefined && request.XHR.status != 0 
	                            && request.XHR.status >= 200 && request.XHR.status < 300){
                                    callback.success(request.XHR);
                            } else {
                                callback.failure(request.XHR);
                            }
                            Connection.DisposeRequest(request);
				        } else {
				            request.TimeOut = request.TimeOut - pollInterval;
				            if (request.TimeOut < 0) {
                                callback.failure(request.XHR);
                                Connection.DisposeRequest(request);
				            }
				        }
			        }
		        ,pollInterval); 

            request.PollID = pollID;
            request.XHR.open('GET', url, true);
            request.XHR.send(null);
            
            return request;
        }
        return null;
    },
    
    IsCallInProgress: function(request) {
        for(i=0; i < this.ActiveTransactions.length; i++) {
            if(this.ActiveTransactions[i] == request) {
                return true;
            }
        }
        return false;
    },
    
    AbortRequest: function(request) {
        request.XHR.abort();
        this.DisposeRequest(request);
    },
    
    GetActiveTransactionCount: function() {
        return this.ActiveTransactions.length;
    },
    
    /*****************************************/
    /**     BEGIN INTERNAL USE FUNCTIONS    **/
    /*****************************************/
    
    GetXmlHttpRequestObject: function() {
        var xhr;
        try {
            xhr = new XMLHttpRequest();
        } catch(e) {
            try {
                xhr = new ActiveXObject('MSXML2.XMLHTTP.3.0');
            } catch(e) {        
                try {            
                    xhr = new ActiveXObject('MSXML2.XMLHTTP');
                } catch(e) {                   
                    xhr = new ActiveXObject('Microsoft.XMLHTTP');
                }
            }
        }
        return xhr;
    },
    
    DisposeRequest: function(request) {
        window.clearInterval(request.PollID);
        for(i=0; i < this.ActiveTransactions.length; i++) {
            if(this.ActiveTransactions[i] == request) {
                // use splice to keep array length accurate
                this.ActiveTransactions.splice(i,1);
            }
        }
        with(request) {
            delete XHR;
        }
        delete request;
    }
    
    /*****************************************/
    /**     END INTERNAL USE FUNCTIONS      **/
    /*****************************************/
    
}