Ajax = {
    init: function(sXMLFile/*, iThreadNum*/){
        // inicjowanie obiektu do obslugi Ajaxa
        // nazwa pliku do ktorego jest wysylane zapytanie
        // ilosc wotkow ktore na raz obsuguje aplikacja
        this.sXMLFile = sXMLFile;
        this.aQueue = new Array; // kolejka zadan
        this.aInProgressQueue = new Array;
        this.iJobID = 0; //identyfikator w kolejce
        
        this.iIntervalTime = 500;
        this.oRequestInterval = null; // obiekt setTimeout        
        
        this.bActive = false; //okresla stan czy obiekt ma dzialac czy nie
        this.iThreadNum = 1;
        if (arguments.length > 1) { // pobiera argumnet
            var iThreadNum = arguments[1];
            if (parseInt(iThreadNum) > 0) {
                this.iThreadNum = parseInt(iThreadNum);
            } else if (iThreadNum === 0) {
                this.iThreadNum === undefined;
            }
        }
        //this.bAsynchronous = true; // za pomoca zmiennej ustawia sie czy zapytania do serwera maja byc wysylane synchronicznie czy asynchronicznie
        // asynchronicznie czyli wiele zapytan na raz
    },
    oXMLHttpRequest: {
        length: 0,        
        add: function(iID, oXMLHttpRequest) {  
            this[iID] = oXMLHttpRequest;
            this.length++;
        },        
        drop: function(iID) {
            delete this[iID];
            this.length--;
        }
    },
    
    start: function() { // odpala Ajaxa
        this.bActive = true;
        this._startSend();
    },
    
    stop: function() { // zatrzymuje Ajaxa
        this.bActive = false;
    },
    
    setInterval: function(iTime){
        if (parseInt(iTime)) {
            this.iIntervalTime = parseInt(iTime);
            return true;
        }
        return false;
    },
    
    addToQueue: function(sMode, iPriority, aSendValue, aHandlerValue, oHandlerFunction, bPageInstance) {
        // funkcja dodaje zadanie do ajaxowej kolejki
        // sMode - jaki modul ma byc wywolywany (dodawany)
        // iPriority - priorytet w kolejce
        // aSendValue - wartosci wysylane w get do skryptu
        // aHandlerValue - wartosci przekazywane do funkcji
        // oHandlerFunction - funkcja wywolywana po poprawynym wykonaniu zapytania
        var aTmp = {
            iID: ++this.iJobID,
            sMode: sMode,
            iPriority: iPriority,
            aSendValue: aSendValue,
            aHandlerValue: aHandlerValue,
            oHandlerFunction: oHandlerFunction,
            bPageInstance: (bPageInstance?1:0)
        }
        
        if (!this._insertToQueue(aTmp)) {
            return false;
        }
        
        this._startSend();
        
        return this.iJobID; //zwraca identyfiaktor zadania
    },
    
    dropFromQueue: function(iJobID){
        for (var i=0; i < this.aQueue.length; i++ )
        {
            if(this.aQueue[i].iID == iJobID){
                delete this.aQueue.slice(i,i+1);
                return true;                
            }
        }
        return false;
    },
    
    clearQueue: function(){
        // czyszczenie kolejki
        this.aQueue = new Array;
        this.aInProgressQueue = new Array;
        this.iJobID = 0;
    },
    
    _insertToQueue: function(oElement) {
        // dodawanie zadania do kolejki zgodnie z jego priorytetem
        for (var i=0; i < this.aQueue.length; i++ )
        {
            if(this.aQueue[i+1] && this.aQueue[i].iPriority < oElement.iPriority){
                this.aQueue.splice(i, 0, oElement);
                return true;                
            }
        }
        this.aQueue[this.aQueue.length] = oElement;
        return true;
    },
    
    _startSend: function(){
        if (this.aQueue.length && this.bActive && (this.iThreadNum === undefined || this.oXMLHttpRequest.length < this.iThreadNum)/*&& (!this.oXMLHttpRequest || this.oXMLHttpRequest.readyState == 0 || this.oXMLHttpRequest.readyState == 4)*/) {
            this._send(this.aQueue.shift());
            this._startSend();
        } else {
            if (this.aQueue.length) {
                if (this.oRequestInterval) {
                    clearTimeout(this.oRequestInterval);
                }
                setTimeout('Ajax._startSend()', this.iIntervalTime);
            }
            return true;
        }
    },
    
    _send: function(aCurrentJob){
    try{
        if (!(oXMLHttpRequest = this.createXMLHttpRequest())){ // tworzy element HttpRequest
            echo("Błąd podczas tworzenia obiektu XMLHttpRequest");
            return false;
        }
        this.oXMLHttpRequest.add(aCurrentJob.iID, oXMLHttpRequest);
        //this.oXMLHttpRequest[aCurrentJob.iID] = oXMLHttpRequest;
        
        var aPostValue = new Array('thread_id=' + aCurrentJob.iID, 'thread_mode=' + aCurrentJob.sMode, 'thread_page_instance=' + aCurrentJob.bPageInstance);
        for(var sName in aCurrentJob.aSendValue)
        {
            aPostValue[aPostValue.length] = sName + '=' + aCurrentJob.aSendValue[sName];
        }
        
        oXMLHttpRequest.onreadystatechange = function() {Ajax._handle(Ajax.oXMLHttpRequest[eval(aCurrentJob.iID)])};
        oXMLHttpRequest.open('POST', this.sXMLFile, true);
        oXMLHttpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        oXMLHttpRequest.setRequestHeader("Content-length", aPostValue.length);
        oXMLHttpRequest.setRequestHeader("Connection", "close");
        this.aInProgressQueue[aCurrentJob.iID] = aCurrentJob;
        oXMLHttpRequest.send(aPostValue.join('&'));
    } catch(e) {/*alert(e);*/}
    },
    
    _handle: function(oXMLHttpRequest){
        var iReadyState = oXMLHttpRequest.readyState;
        if (iReadyState == 1 || iReadyState == 2 || iReadyState == 3) {
            //alert(iReadyState);
        } else if(iReadyState == 4) {
        try{
            try{ 
                var oResponse = eval('(' + oXMLHttpRequest.responseText + ')');
                var sResponse = null;
                var aInfo = {iID : oResponse.thread_id, sMode : oResponse.thread_mode}
                delete oResponse.thread_id,oResponse.thread_mode;
            } catch(e) {
                var oResponse = null;
                var aTmp = oXMLHttpRequest.responseText.split(':', 3);
                var aInfo = {iID : aTmp[0], sMode : aTmp[1]};
                var sResponse = aTmp[2];
            }
            
            if (!(aInfo.iID.match(/^[0-9]+$/) && aInfo.sMode.match(/^[0-9a-z_-]+$/))) {
                echo(oXMLHttpRequest.responseText.replace(/<[^>]+>/gi,''));
                return false;
            }
            
            if (this.aInProgressQueue[aInfo.iID]) {
                if (this.aInProgressQueue[aInfo.iID].sMode == aInfo.sMode) {
                    if (typeof this.aInProgressQueue[aInfo.iID].oHandlerFunction == 'string') {
                    	eval( this.aInProgressQueue[aInfo.iID].oHandlerFunction + '(this.aInProgressQueue[aInfo.iID].aHandlerValue, oResponse, sResponse);');
                    } else {
                        this.aInProgressQueue[aInfo.iID].oHandlerFunction(this.aInProgressQueue[aInfo.iID].aHandlerValue, oResponse, sResponse);
                    }

                } else {
                    echo('_handle: Bledny mode');
                }
                delete this.aInProgressQueue[aInfo.iID];
            } else {
                echo('_handle: Brak obiektu w tablicy');
                return false;
            }
            
            this.oXMLHttpRequest.drop(aInfo.iID);
            //this._startSend();
        }catch(e){echo('Ajax._handle: '+e)}
        }
    },
    
    createXMLHttpRequest: function()
    {
    	var xmlHttp;
    	try {
    		xmlHttp = new XMLHttpRequest();
    	} catch(e) {
    		var XmlHttpVersions = new Array(
    		"MSXML2.XMLHTTP.5.0",
    		"MSXML2.XMLHTTP.4.0",
    		"MSXML2.XMLHTTP.3.0",
    		"MSXML2.XMLHTTP",
    		"Microsoft.XMLHTTP");
    		for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++)
    			try {
    				xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
    			} catch(e) {}
    	}
    	if (!xmlHttp)
    		return false;
    	else
    		return xmlHttp;
    }    
}
//Funkcja przechwytująca
// function oHandlerFunction( aHandlerValue, oJSONResponse, oTESTResponse)