/*
	Http request class allowing simultaneous requests
  Ladislav Capka lcapka@gmail.com

	based on XmlHttpRequest Wrapper
	Version 1.2.2
	29 Jul 2005
	adamv.com/dev/
*/

var HttpConst = {
	ReadyState: {
		Uninitialized: 0,
		Loading: 1,
		Loaded:2,
		Interactive:3,
		Complete: 4
	},
	Status: {
		OK: 200,

		Created: 201,
		Accepted: 202,
		NoContent: 204,

		BadRequest: 400,
		Forbidden: 403,
		NotFound: 404,
		Gone: 410,

		ServerError: 500
	},
	Cache: {
		Get: 1,
		GetCache: 2,
		GetNoCache: 3,
		FromCache: 4
	},
	Method: {Get: "GET", Post: "POST", Put: "PUT", Delete: "DELETE"}
}

httprequest_parents = new Array();

Http.prototype.Init = function(){
		this._get = this._getXmlHttp()
		this.enabled = (this._get != null)
		this.logging = (window.Logging != null);
  }
Http.prototype._getXmlHttp = function(){
		try {
      if(window.XMLHttpRequest)
        return new XMLHttpRequest();
      else if(window.ActiveXObject){
        var MSXmlVerze = new Array('MSXML2.XMLHttp.6.0','MSXML2.XMLHttp.5.0','MSXML2.XMLHttp.4.0','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp.2.0','Microsoft.XMLHttp');
        for(var i=0;i<=MSXmlVerze.length;i++){
          try{
            xhr=new ActiveXObject(MSXmlVerze[i]);
            return xhr;
          }catch(e){}
        }
      }
    }
		catch (e) {}

		return null;
	}

/*
	Params:
		url: The URL to request. Required.
		cache: Cache control. Defaults to Cache.Get.
		callback: onreadystatechange function, called when request is completed. Optional.
		method: HTTP method. Defaults to Method.Get.
*/
Http.prototype.get = function(params, callback_args){
		if (!this.enabled) throw "Http: XmlHttpRequest not available.";
		httprequest_parents.push([this._get,this]);

		var url = params.url;
		if (!url) throw "Http: A URL must be specified";

		var cache = params.cache || HttpConst.Cache.Get;
		var method = params.method || HttpConst.Method.Get;
		var callback = params.callback;

		if ((cache == HttpConst.Cache.FromCache) || (cache == HttpConst.Cache.GetCache))
		{
			var in_cache = this.from_cache(url, callback, callback_args)

			if(this.logging){
				Logging.log(["Http: URL in cache: " + in_cache]);
			}

			if(in_cache || (cache == HttpConst.Cache.FromCache)) return in_cache;
		}

		if(cache == HttpConst.Cache.GetNoCache){
			var sep = (-1 < url.indexOf("?")) ? "&" : "?"
			url = url + sep + "__=" + encodeURIComponent((new Date()).getTime());
		}

		// Only one request at a time, please
		if((this._get.readyState != HttpConst.ReadyState.Uninitialized) &&
			(this._get.readyState != HttpConst.ReadyState.Complete)){
			this._get.abort();

			if(this.logging){
				Logging.log(["Http: Aborted request in progress."]);
			}
		}
		
 	  this._get.open(method, url, true);

		this._get.onreadystatechange = function(){
      var p=null,x=null;
			for(var i=0;i<httprequest_parents.length;i++){
        if((httprequest_parents[i][0] == this) || (httprequest_parents[i][2] == this)){
          p=httprequest_parents[i][1];
          x=this;
          break;
        }
      }
      if(p===null){
        for(var i=0;i<httprequest_parents.length;i++){
          if((httprequest_parents[i][0]!==null) && (httprequest_parents[i][0].readyState == HttpConst.ReadyState.Complete)){
            p=httprequest_parents[i][1];
            x=httprequest_parents[i][0];
            httprequest_parents[i][0]=null;
            break;
          }
        }
      }
      if((p===null)||(x===null))return; // Unknown request...
			if(x.readyState != HttpConst.ReadyState.Complete) return; // Unfinished request

			if(p.logging){
				Logging.log(["Http: Returned, status: " + x.status]);
			}

			if ((cache == HttpConst.Cache.GetCache) && (x.status == HttpConst.Status.OK)){
				p._cache[url]=x.responseText;
			}

			if (callback_args == null) callback_args = new Array();

			var cb_params = new Array();
			cb_params.push(p._get);
			for(var i=0;i<callback_args.length;i++)
				cb_params.push(callback_args[i]);

			callback.apply(null, cb_params);
		}
		
		if(this.logging){
			Logging.log(["Http: Started\n\tURL: " + url + "\n\tMethod: " + method + "; Cache: " + Hash.keyName(HttpConst.Cache,cache)])
		}

		this._get.send(params.body || null);
	}

Http.prototype.from_cache = function(url, callback, callback_args){
		var result = this._cache[url];

		if (result != null) {
			var response = new this.CachedResponse(result)

			var cb_params = new Array();
			cb_params.push(response);
			for(var i=0;i<callback_args.length;i++)
				cb_params.push(callback_args[i]);

			callback.apply(null, cb_params);

			return true
		}
		else
			return false
	}

Http.prototype.clear_cache = function(){
		this._cache = new Object();
	}

Http.prototype.is_cached = function(url){
		return this._cache[url]!=null;
	}

Http.prototype.CachedResponse = function(response){
		this.readyState = HttpConst.ReadyState.Complete;
		this.status = HttpConst.Status.OK;
		this.responseText = response;
	}

function Http(){
  this.enabled=false;
  this.logging=false;
  this._get=null;
  this._cache=new Object();

  this.Init();
  return this;
}

