// --------------------------
// GLOBAL DECLARATIONS
// --------------------------

/* public constant declarations */

var _XML_DEFAULT_HTTP_TIMEOUT = 10;
var _XML_DEFAULT_HTTP_VERB_GET = "GET";
var _XML_DEFAULT_HTTP_VERB_POST = "POST";
var _XML_DEFAULT_HTTP_VERB_HEAD = "HEAD";

// XML-HTTP Data Fetcher
// ^^^^^^^^^^^^^^^^^^^^^
//
//    Parameter      Type     Required  Description
//    --------       ----     --------  -----------
// 1  HTTP Verb      string   Yes       HTTP verb to use when requesting the resource
// 2  URL            string   Yes       URL of web resource to retrieve
// 3  Data           string   No        Data to send to the server, can be null
// 4  Callback       object   No        Function to call when request completed, can be null
//
function xml_http_request()
{
    /* DECLARATIONS */

	/* private variables */
    var _this = this;               // do not remove - required for object referencing!
    var _arguments = xml_http_request.arguments;
    var _startTime = 0;             // number of milliseconds since midnight, January 1, 1970 UTC
    var _request_time = 0.0;        // time taken for the last request to execute
    var _http_verb = "";            // otherwise known as the http method - get, post, etc.
    var _http_url = "";             // target url to fetch
    var _http_data = null;          // data to transmit to the host
    var _client_callback = null;    // client function to call when finished
    /* public properties */
    _this.HTTP = null;              // xmlhttp object
    _this.Fetching = false;         // flags whether the object is currently fetching
    /* public methods */
    _this.Reset = Initialize;       // re-initializes the object, effectively resetting it
    _this.Fetch = Fetch;            // starts the fetch routine
    _this.__ProcessReadyState = ProcessReadyState;
    /* CONSTRUCTOR */

    Initialize();

    /* MAIN METHODS */

    function Initialize()
    {
        // get instantiation arguments
        var args = (_arguments) ? _arguments : new Array();
        // initialize variables
	    _this.Fetching   = false;
        _http_verb       = (args.length >= 2) ? (args[0]) ? args[0] : _XML_DEFAULT_HTTP_VERB_GET : _XML_DEFAULT_HTTP_VERB_GET;
        _http_url        = (args.length >= 2) ? (args[1]) ? args[1] : ""   : "";
        _http_data       = (args.length >= 3) ? (args[2]) ? args[2] : null : null;
        _client_callback = (args.length >= 4) ? (args[3]) ? args[3] : null : null;
        // instantiate objects
	    _this.HTTP         = null;
	    /*@cc_on @*/
	    /*@if (@_jscript_version >= 5)
		    try {
			    _this.HTTP = new ActiveXObject("Msxml2.XMLHTTP");
		    } catch (e) {
			    try {
				    _this.HTTP = new ActiveXObject("Microsoft.XMLHTTP");
			    } catch (E) {
				    _this.HTTP = false;
			    }
		    }
	    @end @*/
	    if (_this.HTTP == null && typeof XMLHttpRequest != 'undefined') {
		    try {
			    _this.HTTP = new XMLHttpRequest();
		    } catch (e) {
			    _this.HTTP = null;
		    }
	    }
	    if (_this.HTTP == null && window.createRequest) {
		    try {
			    _this.HTTP = window.createRequest();
		    } catch (e) {
			    _this.HTTP = null;
		    }
	    }
    }

    function Fetch()
    {
        // return false if can't fetch
        if (_http_url == "" || _this.HTTP == null || _this.Fetching) { return false; }
        // update the object's state
        _this.Fetching = true;
        // save the start time
        _startTime = (new Date()).valueOf();
        // initialize the http object and request the resource
        _this.HTTP.open(_http_verb, _http_url, true);
        _this.HTTP.onreadystatechange = _this.__ProcessReadyState;
        _this.HTTP.send((_http_data) ? _http_data : "")
        // resource requested, return indication of positive result
        return true;
    }

    function ProcessReadyState()
    {
        // return if it's not fetching anything
        if (!_this.Fetching) { return; }
        // calculate the request duration
        _request_time = ((new Date()).valueOf() - _startTime) / 1000;
        // has it finished fetching?
        if (_this.HTTP.readyState == 4)
        {
            // update statistics and execute the callback function
            _this.Fetching = false;
            if (_client_callback)
            {
                _client_callback(_this.HTTP);
            }
        }
        // hasn't finished fetching, but has it timed-out?
        else if (_request_time >= _XML_DEFAULT_HTTP_TIMEOUT)
        {
            // stop the request by resetring the object
            _this.Reset();
            // update statistics and execute the callback function
            _this.Fetching = false;
            if (_client_callback)
            {
                _client_callback(_this.HTTP);
            }
        }
    }
}

