/*************************************************************************************

Javascript by Robby Ticknor for Swimbo inc.  2007

*************************************************************************************/






//********************  Queue  **********************

function PriorityQueue(fnCompare) {

    this._items = new Array();
    if (typeof fnCompare == "function")
        this._compare = fnCompare;


}

PriorityQueue.prototype = {


    _compare : function (oValue1, oValue2){
        if (oValue1 < oValue2) {
                return -1;
            }else if (oValue1 > oValue2){
                return 1;
            }else{
                return 0;
            }
    
    },
    
    get : function (){
        return this._items.shift();
    },
    
    item : function (iPos){
        return this._items[iPos];
    },
    
    peak : function (){
        return this._items[0];
    },
    
    
    prioritize : function(){
        this._items.sort(this._compare);
    },
    
    put : function (oValue){
        this._items.push(oValue);
        this.prioritize();
    
    },


    remove : function (oValue){
        for (var i = 0; i < this._items.length; i++){
            if (this._items[i] === oValue){
                this._items.splice(i,1);
                return true;
            }
        }
        return false;
    },


    size : function (){
        return this._items.length;
    }
}



var RequestManager = (function () {

    var oManager = {
    
        DEFAULT_PRIORITY: 10,
        
        INTERVAL : 200,
        
        AGE_LIMIT : 60000,
        
        _active : new Array(),
    
        _pending : new PriorityQueue (function (oRequest1, oRequest2){
            return oRequest1.priority - oRequest2.priority;
         }),
         
         
         _agePromote : function (){
         
            for (var i = 0; i < this._pending.size(); i++){
                var oRequest = this._pending.item(i);
                oRequest.age += this.INTERVAL;
                if (oRequest.age >= this.AGE_LIMIT){
                    oRequest.age = 0;
                    oRequest.priority --;
                }
            }
            this._pending.prioritize();
         
         },
         
         _checkActiveRequests : function () {
            
            var oRequest = null;
            var oTransport = null;
            
            for (var i = this._active.length - 1; i >= 0; i--){
            
                oRequest = this._active[i];
                oTransport = oRequest.transport;
                
                if (oTransport.readyState == 4){
                    oRequest.active = false;
                    this._active.splice(i,1);
                    var fnCallback = null;
                    if (oTransport.status >= 200 && oTransport.status < 300){
                        if (typeof oRequest.onsuccess == "function"){
                            fnCallback = oRequest.onsuccess;
                        }
                    }else if (oTransport.status == 304) {
                        if (typeof oRequest.onnotmodified == "function" ) {
                            fnCallback = oRequest.onnotmodified;
                        }
                    } else {
                        if (typeof oRequest.onfailure == "function"){
                            fnCallback = oRequest.onfailure;
                        }
                    }
                    if (fnCallback != null) {
                        setTimeout ((function (fnCallback, oRequest, oTransport){
                            return function () {
                                fnCallback.call (oRequest.scope || window, {
                                    status : oTransport.status,
                                    date : oTransport.responseText,
                                    request : oRequest});
                            }
                       })(fnCallback, oRequest, oTransport),1);
                  }
              }
          }
         },
         
         
         _createTransport : function (){
            if (typeof XMLHttpRequest != "undefined"){
                return new XMLHttpRequest();
            } else if (typeof ActiveXObject != "undefined"){
                var oHttp = null;
                try {
                    oHttp = new ActiveXObject("MSXML2.XmlHttp.6.0");
                    return oHttp;
                }catch (oEx) {
                    try {
                        oHttp = new ActiveXObject("MSXML2.XmlHttp.3.0"); 
                        return oHttp;
                    } catch (oEx2) {
                        throw Error("Cannot create XMLHttp Object.");
                    }
                }
            }
         },
         
         
         _sendNext : function () {
            if (this._active.length < 2) {
                var oRequest = this._pending.get();
                if (oRequest != null) {
                    this._active.push(oRequest);
                    oRequest.transport = this._createTransport();
                    oRequest.transport.open (oRequest.type, oRequest.url, true);
                    if (oRequest.type == 'post'){
                        try{
                            oRequest.transport.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                        }catch (oEX){
                            throw Error("Error adding Content-Type to Post: " + oEX);
                        }
                    }
                    oRequest.transport.send(oRequest.data);
                    oRequest.active = true;
                }
            }
         },
         
         
         cancel : function (oRequest) {
            if (!this._pending.remove(oRequest)){
            
                oRequest.transport.abort();
                
                if (this._active[0] === oRequest){
                    this._active.shift();
                } else if (this._active[1] === oRequest) {
                    this._active.pop();
                }
                
                if (typeof oRequest.oncancel == "function") {
                    oRequest.oncancel.call(oRequest.scope || window, {request : oRequest});
                }
            }
           
         },
         
         
         poll : function (oRequest){
            oRequest.priority = 3;
            this.send(oRequest);
         },
         
          prefetch : function (oRequest){
            oRequest.priority = 5;
            this.send(oRequest);
         },
         
         
         
         send : function (oRequest){
            if (typeof oRequest.priority != "number"){
                oRequest.priority = this.DEFAULT_PRIORITY;
                }
           oRequest.active = false;
           oRequest.age = 0;
           this._pending.put(oRequest);
         },
         
          submit : function (oRequest){
            oRequest.priority = 0;
            this.send(oRequest);
         },
         
          submitPart : function (oRequest){
            oRequest.priority = 2;
            this.send(oRequest);
         }
         
         
    };
    
    
    //init
    setInterval (function () {
        RequestManager._checkActiveRequests();
        RequestManager._sendNext();
        RequestManager._agePromote();
     }, oManager.INTERVAL);

    return oManager;


})();



