/*

**

** Implementation of basic AJAX functionality using pooling of the XmlHttpRequest objects and callbacks

**

*/



//Helper functions



//Get the text value incorporated in the node (ex. <text>txt</text>

function getXmlNodeText(base, nodeName)

{

    var nodes = base.getElementsByTagName(nodeName);

    if(nodes.length==0)

        return "";



    if(nodes[0].childNodes.length==0)

        return "";

    if(nodes[0].firstChild.nodeValue==null)

        return "";

    return nodes[0].firstChild.nodeValue;

}



//Create a binding so the function is called with the correct this pointer.

// fnc should be the string name of a function of ptr

function bind(ptr, fcn)

{

    return (function(x) { return function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { x[fcn](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) }; })(ptr);

}



//AJAX class

function AJAX(thisUserID)

{

    this.thisUserID = thisUserID;           //FIXME

    this.pool = new Array();                //Pooling of AJAX objects

    this.pool.push(this.createXHR());

    this.url = 'http://'+document.domain+'/include/page/chat/chatServer.php';

}



//Get a new instance of the XmlHttpRequest object

AJAX.prototype.getInstance = function()

{

    var xhr;

    if(this.pool.length<1)

        xhr = this.createXHR();

    else

        xhr = this.pool.pop();    

    return xhr;

}



AJAX.prototype.releaseInstance = function(xhr)

{

    this.pool.push(xhr);

}

 

//Assume args is an associative array with key-value pairs

AJAX.prototype.argsToQuery = function(args)

{

    args['thisID'] = this.thisUserID;       //FIXME

    

    var qs = "";

    var first=true;

    for(var k in args)

    {

        if(!first)

            qs += '&';

        qs += k + '=' + args[k];

        first=false;

    }

    return qs;

}



//Create the callback function for the ASync requests

// Function waits for ready state to be complete and then checks the status

function generateCallbackFunction(_this, xhr, ok, fail)

{

    return function() { if(xhr.readyState==4) {

                            if(xhr.status==200) {

                                try {

                                    if(typeof(ok)=='function')

                                        ok(xhr);

                                } catch(e) {       //FIXME: temporary solution to get errors on response

                                    if(typeof(log)!='undefined') {

                                        log.display('Error processing the ajax response. Response text:');

                                        log.display(xhr.responseText);

                                        log.displayHTML(xhr.responseText);

                                    }

                                    _this.releaseInstance(xhr);

                                    throw e;

                                }

                            } else {

                                if(typeof(fail)=='function')

                                    fail(xhr);

                            }

                            _this.releaseInstance(xhr);

                        }

                      }

}



//Make an async post request and use one of the two callbacks to handle the result

AJAX.prototype.postAsync = function(args, responseReady, postFailed)

{

    var request = this.getInstance();

    request.open("POST", this.url, true);

    request.onreadystatechange = generateCallbackFunction(this, request, responseReady, postFailed);

    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    request.send(this.argsToQuery(args));

    

    //log.display('Async post: ' + this.argsToQuery(args));

}



//Make an async get request and use one of the two callbacks to handle the result

AJAX.prototype.getAsync = function(args, responseReady, postFailed)

{

    var u = this.url + '?' + this.argsToQuery(args);

    var request = this.getInstance();

    request.open("GET", u, true);

    request.onreadystatechange = generateCallbackFunction(this, request, responseReady, postFailed);

    request.send(null);

    

    //log.display('Async get: ' + u);

}



//Make a sync post request and use one of the two callbacks to handle the result (or set handlers to null)

AJAX.prototype.postSync = function(args, responseReady, postFailed)

{

    var request = this.getInstance();

    request.open("POST", this.url, false);

    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    request.onreadystatechange = function() {};

    request.send(this.argsToQuery(args));

    

    //log.display('Sync post: ' + this.argsToQuery(args));

    

    var func = generateCallbackFunction(this, request, responseReady, postFailed);

    func();

}



//Make a sync get request and use one of the two callbacks to handle the result (or set handlers to null)

AJAX.prototype.getSync = function(args, responseReady, postFailed)

{

    var u = this.url + '?' + this.argsToQuery(args);

    var request = this.getInstance();

    request.open("GET", u, false);

    request.onreadystatechange = function() {};

    request.send(null);

    

    //log.display('Sync get: ' + u);



    var func = generateCallbackFunction(this, request, responseReady, postFailed);

    func();

}



//Create a new XMLHttpRequest object

AJAX.prototype.createXHR = function()

{

	if (window.XMLHttpRequest)      //native XMLHttp req.

    {

		var c = new XMLHttpRequest();

	}

    else if(window.ActiveXObject) 	//IE/Windows ActiveX version

    {

		var progids = new Array('MSXML2.XMLHTTP.5.0',

                                'MSXML2.XMLHTTP.4.0',

			                    'MSXML2.XMLHTTP.3.0',

                                'MSXML2.XMLHTTP',

                                'Microsoft.XMLHTTP');

		for(var i=0; i<progids.length; i++) {

			try {

				c = new ActiveXObject(progids[i]);

                break;

			} catch (e) {}

		}

	}

	return c;

}

