/**
 * Create loader to request data from server
 * Uses it_http class for communication
 *
 * @param handler Object providing clear()/render() function when data arrives
 */
function it_loader(handler)
{
	/* Clear cache etc. if completely new data */
	this.http = null;
	this.handler = handler;
	this.callback = { object:this, method:'dataReady', errorhandler:'onerror' };
	this.clear();
}

/* Methods */
it_loader.prototype =
{

/* Clear cache and initialize handler */
clear: function()
{
	/* Clear cache etc. if completely new data */
	this.entry = new Array();
	this.start = this.end = 0;
	this.attr = { num: 0, loadtime: 0 };

	if (this.handler.clear)
		this.handler.clear();
},

load: function(baseurl, pos, num, query_volatile, retry)
{
	/* Convert to int */
	pos -= 0;
	num -= 0;

	if (isNaN(retry))
		retry = 0;

	if (baseurl != this.baseurl)
	{
		this.clear();
		this.baseurl = baseurl;
		this.start = this.end = pos;
	}

	this.pos = pos;
	this.num = num;
	this.query_volatile = query_volatile;

	this.stop();

	while ((num > 0) && (typeof this.entry[pos] != "undefined"))
	{
		pos++;
		num--;
	}

	if (this.attr.eof)
		num = Math.min(num, this.end - pos);

	if (num > 0)
	{
		this.retry = retry;
		this.http = it_http.get_instance();
		this.http.get(baseurl + (baseurl.match(/\?/) ? "&" : "?") + "pos=" + pos + "&num=" + num + (retry ? "&retry=" + retry : "") + (query_volatile ? query_volatile : ""), this.callback);
	}
	else
		this.handler.render(this);

	return true;
},

/* deprecated: use it_http::post() instead */
post: function(baseurl, data)
{
	this.clear();
	this.http = it_http.get_instance();
	this.http.post(baseurl, data, this.callback);
},

retryload: function(p)
{
	this.load(p.baseurl, p.pos, p.num, p.query_volatile, p.retry);
},

dataReady: function(data)
{
	if ((typeof data == "object"))
	{
		this.attr = {};

		for (var key in data)
		{
			var value = data[key];
			var id = key - 0;

			if (!isNaN(id))
			{
				this.start = Math.min(this.start, id);
				this.end = Math.max(this.end, id + 1);
				this.entry[id] = data[key];
			}
			else
				this.attr[key] = data[key];
		}

		if (this.attr.eof)
			this.attr.num = this.end;	/* Fix bogus # of result value */

		this.handler.render(this);

		if (!this.attr.eof && (this.end < this.pos + this.num))
			this.load(this.baseurl, this.end, this.pos + this.num - this.end);

		it_loader.sequence += "h";
		this.http = null;
	}
},

onerror: function(response)
{
	var retry = this.retry + 1;

	if (retry < 10)
		it_timer({ object: this, method: "retryload", timeout: Math.pow(5, Math.min(retry, 5)), baseurl: this.baseurl, pos: this.pos, num: this.num, query_volatile: this.query_volatile, retry: retry });
	else
		ED(response);
},

stop: function()
{
  if (this.http)
    this.http.stop();
} /* NO COMMA */

}

// static properties
it_loader.sequence = "";