Function.EnsureNamespace('Inrix');

Inrix.Request=function(params,url,method,timeout,contentType){
    var _this=this;
    var _cancelTimer=0;
    var _asXml=false;
    var _disposable=true;
    var _aborted;
    
    var _transport;
    var _callbacks={
        success:null,
        failure:null,
        timeout:null
    };
    
    this.Url=url||"Proxy.ashx";
    this.Method=method || "POST";
    this.ContentType=contentType || "application/x-www-form-urlencoded";
    this.Params=params||{};
    this.Timeout=timeout||3000;
    
    this.initialize=function(){
        _disposable=false;
    }
    
    this.dispose=function(){
        this.abort();
        for(var x in this.Params)this.Params[x]=null;
        //_transport=null;
    }
    
    this.abort=function(){
        _aborted=true;
        abort();
    }
    
    //asynchronous request
    this.beginRequest=function(callbackSuccess,callbackFailure,callbackTimeout,asXml){
        _asXml=!!asXml;
        _aborted=false;
        _callbacks.success=callbackSuccess;
        _callbacks.failure=callbackFailure;
        _callbacks.timeout=callbackTimeout;
        send(true)
    }
    this.endRequest=function(callback,status,result,info){
		if(_aborted)return;
		if(typeof(callback)=='function')callback(result,info);
		else if(info)throw info;
    }
    
    //synchronous request
    this.sendRequest=function(asXml){
        _asXml=!!asXml;
        _aborted=false;
        for(var x in _callbacks)_callbacks[x]=null;
        return send();
    }
    
    function buildParamList(){
        var ret=[];
        for(var x in _this.Params)ret.push(String.Format("{0}={1}",x,encodeURIComponent(_this.Params[x])));
        return ret.length?ret.join('&'):null;
    }
    
    function send(async){
        var transport=_transport=ensureTransport();
        transport.open(_this.Method, _this.Url, !!async);
        if(_this.ContentType)transport.setRequestHeader("Content-Type", _this.ContentType);
        //transport.setRequestHeader("Accept-Encoding","gzip, deflate");
        //transport.setRequestHeader("Accept-Charset","utf-8");
        if(async){
            if(_this.Timeout>0)_cancelTimer=setTimeout(requestTimeout,_this.Timeout);
            transport.onreadystatechange=readyStateChange;
        }
        var params=buildParamList();
        if(params)transport.send(params);
        else transport.send();
        if(!async)return handleTransportResult(transport);
    }

    function abort() {
        try{
            if(_transport)_transport.abort();
        }catch(e){
        }
    }
    
    function requestTimeout(){
        abort();
        if(_this.endRequest)_this.endRequest(_callbacks.timeout,'timeout',null,'Inrix.Request.send: Request timed out.');
    }
    
	function readyStateChange(){
		if(!_transport||_transport.readyState!=4)return;
		if(_cancelTimer)clearTimeout(_cancelTimer);
		try{
			var result=handleTransportResult(_transport);
			if(Object.IsType(Function,_this.endRequest))_this.endRequest(_callbacks.success,'success',result);
		}catch(e){
			if(Object.IsType(Function,_this.endRequest))_this.endRequest(_callbacks.failure,'failure',_transport.responseText,e);
        }
        if(_disposable)_this.dispose();
	}

    
	function ensureTransport(){
		var transport=createTransport();
		if(!transport)alert("Inrix.Request: Unable to create http request.");
		    //throw new Error("Inrix.Request: Unable to create http request.");
		return transport;
	}
	function createTransport(){
		if(typeof(XMLHttpRequest)!='undefined')return new XMLHttpRequest();
		if(typeof(ActiveXObject)!='undefined')return new ActiveXObject('Microsoft.XMLHTTP');
		return null;
	}
	function handleTransportResult(transport){

//TODO: catch and handle 302/login.aspx redirects

		if(!transport||(transport.status&&transport.status!=200)){
		    //throw new Error(String.Format('Inrix.Request: Unable to retrieve url: {0}\nStatus: {1}\n\n{2}',_this.Url,transport.status,transport.responseText));
		    //alert('Inrix.Request: Unable to retrieve request.');
		    return null;
		}
		if(_asXml)return transport.responseXML;
		var result=transport.responseText+"";
		if(result.indexOf("{\"error\":")==0){
		    var info=Object.FromJson(result);
		    throw new Error(info&&info.error||result);
		}
		result.headers=getResponseHeaders(transport);
		return result;
	}
	function getResponseHeaders(transport){
		var headers=[
			'Content-Encoding',
			'Content-Length'
		];
		var ret={};
		for(var i=0;i<headers.length;i++)ret[headers[i]]=transport.getResponseHeader(headers[i]);
		return ret;
	}
}
