var XHR = function(){

}

XHR.prototype.request =  null;

XHR.prototype.getNewRequest = function(options){

    var request;
    var s = ["XMLHttpRequest()",
             "ActiveXObject(\"Msxml2.XMLHTTP\")",
             "ActiveXObject(\"Microsoft.XMLHTTP\")"
            ]

    for(var x in s){
        try {
            eval("request = new " + s[x] + ";");
            if(request){
                break;
            }
        } catch (e) {continue;}
    }

    var _this = this;

    request.onreadystatechange = function(){
        if(request.readyState == 4){
            if(_this.timer) {
                clearTimeout(_this.timer);
            }                

            if(request.status == 200) {
                if(options.callback)
                    options.callback(request);
            } else {
                if(options.errorCallback)
                    options.errorCallback(request);
                else
                    options.callback(null);
            }

        }
    }

    return request;

}



XHR.prototype.startTimer = function(request, options){

    if(options.timeoutCallback){
        var _this = this;
        this.timer = setTimeout(function(){
            request.abort();
            options.timeoutCallback(request);

        }, options.timeout);
    }

}

XHR.prototype.clearTimer = function(request){
    if(this.timer) {
        var _this = this;
        clearTimeout(_this.timer);
    }
}


XHR.prototype.doSend = function(opts){
    clearTimeout(this.timer);
    var method = opts.method.toUpperCase();
    var isGet = method == "GET";
    var isPost = method == "POST";

    var params = this.encodeKVP(opts.params);
    var body = isPost ? params : null;
    var async = (opts.async == null || opts.async == undefined || opts.async == true) ? true : false;

    var request = this.getNewRequest(opts);
    var query = isGet && params != "" && params != null ? "?" + params : "";
    request.open(method, opts.url + query, async);

    if(!opts.header && isPost)
        request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

    this.startTimer(request, opts);
    request.send(body);

    return request;

}


XHR.prototype.get = function(opts){
    opts.method = "GET";
    return this.doSend(opts);

}

XHR.prototype.post = function(opts){
    opts.method = "POST";
    return this.doSend(opts);

}

XHR.prototype.encodeKVP = function (kvp) {

    var s = "";
    var reg = /%20/g;
    var pairs = [];
    for(var x in kvp){

        pairs.push(encodeURIComponent(x).replace(reg, "+") + "=" 
                   + encodeURIComponent(kvp[x]).replace(reg, "+"));
    }

    return pairs.join("&");

}

XHR.prototype.getBaseOpts = function (){ 

    return {"method" : "GET",
            "timeout" : 10000,
            "params" : null,
            "async" : false
           }; 
}
