/**************************************************************************
    HTTPClient: a convenience wrapper around XMLHTTPRequests
    <l.m.orchard@pobox.com> http://www.decafbad.com
    Share and Enjoy.  
**************************************************************************/

function HTTPClient(handler) { this.init(handler) };

HTTPClient.prototype = {
    
    GET: function(url, qargs, user, passwd) 
        { this.doMethod('GET', url, qargs, null, user, passwd); },
    PUT: function(url, qargs, data, user, passwd) 
        { this.doMethod('PUT', url, qargs, data, user, passwd); },
    POST: function(url, qargs, data, user, passwd) 
        { this.doMethod('POST', url, qargs, data, user, passwd); },
    DELETE: function(url, qargs, user, passwd) 
        { this.doMethod('DELETE', url, qargs, null, user, passwd); },
    HEAD: function(url, qargs, user, passwd) 
        { this.doMethod('HEAD', url, qargs, null, user, passwd); },

    doMethod: function(method, url, qargs, data, user, passwd) {
        qargs = qargs || {};
        
        // HACK: This is an attempt to defeat caching on MSIE
        if (this.defeat_cache) {
            qargs['__'] = (new Date()).getTime();
        }
        
        if (browser == "Safari") {
            // HACK: Bah, Safari doesn't support anything but GET & POST
            if (! ((method == "GET") || (method == "POST")) ) {
                qargs['method'] = method;
                method = "POST";
            } 
        }
        
        url = this.buildQueryString(url, qargs);
        this.reset();
        this.op = method;
        this.log.debug2(method+" " + url);
        this.req.open(method, url, true, user, passwd);
        this.req.send(data);
    },
    
    init: function(handler) {
        // Try to get a working, preferrably global log instance
        if (window.log)
            this.log = window.log;
        else
            this.log = new Log(null);
    
        this.handler = handler;
        this.setDefeatCache(false);
        this.reset();
    },

    setDefeatCache: function(fl) {
        this.defeat_cache = fl;
    },
    
    reset: function() {
        // http://jibbering.com/2002/4/httprequest.2004.html
        var xmlhttp=false;
        /*@cc_on @*/
        /*@if (@_jscript_version >= 5)
        // JScript gives us Conditional compilation,
        // we can cope with old IE versions.
        // and security blocked creation of the objects.
         try {
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
         } catch (e) {
          try {
           xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
          } catch (E) {
           xmlhttp = false;
          }
         }
        @end @*/
        if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
          xmlhttp = new XMLHttpRequest();
        }
        
        var that = this;
        this.req = xmlhttp;
        this.req.onreadystatechange = function() { that._state() };
    },

    _state: function() {
        var h = this.handler;
        switch (this.req.readyState) {
            case 0: // init
                this.log.debug3("\t...initialized");
                if (h.onInit) h.onInit(this);
                break;
            case 1: // loading
                this.log.debug3("\t...loading");
                if (h.onLoading) h.onLoading(this);
                break;
            case 2: // loaded
                this.log.debug3("\t...loaded");
                if (h.onLoaded) h.onLoaded(this);
                var s_no;
                var s_txt;
                // HACK: Throws unhelpful errors.
                try {
                    s_no  = this.req.status;
                    s_txt = this.req.statusText;
                } catch(e) { }
                if (s_no >= 400) {
                    //this.req.abort();
                    if (h.onError) h.onError(this, s_no, s_txt);
                }
                break;
            case 3: // interactive
                this.log.debug3("\t...interactive");
                if (h.onInteractive) h.onInteractive(this);
                break;
            case 4: // complete
                this.log.debug3("\t...complete");
                if (this.req.status == 200) {
                    if (h.onTextComplete) 
                        h.onTextComplete(this, this.req.responseText);
                    if (h.onXMLComplete)  
                        h.onXMLComplete(this, this.req.responseXML);
                }
                if (h.onComplete) h.onComplete(this);
                break;
        }
    },

    buildQueryString: function(url, qargs) {
        if (!qargs) return url;
        var v=[]; 
        for (var k in qargs)
            v[v.length] = escape(k)+"="+escape(qargs[k]); 
        if (v.length > 0)
            return url + '?' + v.join('&');
        else
            return url
    }
    
};


