/* # vim:set filetype=javascript: */




// Constructor for generic HTTP client
function cpfHTTPClient() {};

// Create XMLHttpRequest
function getXMLHTTP () {
	var ret;

	if( !window.XMLHttpRequest ) {
        try { ret = new ActiveXObject("MSXML3.XMLHTTP") } catch (e) {}
        try { ret = new ActiveXObject("MSXML2.XMLHTTP.3.0") } catch (e) {}
        try { ret = new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
        try { ret = new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}

	} else {
		ret = new XMLHttpRequest ();
	}

	if (! ret) 
		throw new Error("Could not find an XMLHttpRequest alternative.");

	return ret;
}

// Add methods and properties as array
cpfHTTPClient.prototype = {
    url: null,

    // Instance of XMLHttpRequest
    xmlhttp: null,

    // Used to make sure multiple calls are not placed
    // with the same client object while another in progress
    callinprogress: false,

    // The user defined handler - see MyHandler below
    userhandler: null,

    init: function (url) {
        this.url = url;
        this.xmlhttp = new getXMLHTTP ();
    },

    // handler argument is a user defined object to be called
    asyncGET: function (handler, purl) {
		var requrl = purl;

        // Prevent multiple calls
        if (this.callinprogress) {
            throw "Call in progress";
        };

		this.callinprogress = true;

		if (! requrl) requrl = this.url; 
		if (! requrl) throw "Invalid URL";

        this.userhandler = handler;

        // Open an async request - third argument makes it async
        this.xmlhttp.open ('GET', requrl, true);

        // Have to assign "this" to a variable - not sure why can't use directly
        var self = this;

        // Assign a closure to the onreadystatechange callback
        this.xmlhttp.onreadystatechange = function() {
            self.stateChangeCallback (self);
        }

        // Send the request
        this.xmlhttp.send (null);
    },

    stateChangeCallback: function (client) {
        switch (client.xmlhttp.readyState) {

            // Request not yet made
            case 1:
                try {
                    client.userhandler.onInit();
                } catch (e) { /* Handler method not defined */ }
            break;

            // Contact established with server but nothing downloaded yet
            case 2:
				var status;
				try {
					status = client.xmlhttp.status;
				} catch (e) {
					status = 200;
				}

				// Check for HTTP status 200
				if ( status != 200 ) {
					try {
						client.userhandler.onError (
							client.xmlhttp.status, client.xmlhttp.statusText);
					} catch (e) {
						/* Handler not defined */
					} finally  {

						// Abort the request
						client.xmlhttp.abort();

						// Call no longer in progress
						client.callinprogress = false;
					}
				}

            break;

            // Called multiple while downloading in progress
            case 3:
                // Notify user handler of download progress
                try {
                    // Get the total content length
                    // -useful to work out how much has been downloaded
                    try {
                        var contentLength = 
                            client.xmlhttp.getResponseHeader ("Content-Length");
                    } catch (e) {
                        var contentLength = NaN;
                    } 

                    // Call the progress handler with what we've got
                    client.userhandler.onProgress (
                        client.xmlhttp.responseText,
                        contentLength
                    );

                } catch (e) { /* Handler method not defined */ }
            break;

            // Download complete
            case 4:
                try {
                    client.userhandler.onLoad(client.xmlhttp);
                } catch (e) {
                    /* Handler method not defined */
                } finally {
                    // Call no longer in progress
                    client.callinprogress = false;
                }
            break;
        }
    }
};

