

// Opera on the Nokia 770 seems to have a problem with the xml document returned from
// responseXML.  This work around uses regex to fake calls to getElementsFromTagName() ...
// this is not as effective as a proper parse of the xml, and only supports .firstChild.nodeValue
// on the result, but it should suffice for the jukebox.

function OperaNokia_NodeValue(text)
{
	this.nodeValue = text;
}

function OperaNokia_Child(text)
{
	this.firstChild = new OperaNokia_NodeValue(text);
	this.getElementsByTagName = function(tagName)
		{
			var remaining = this.firstChild.nodeValue.replace(/[\r\n]+/g, ' ');
			var ret = new Array();
			var re = new RegExp("<" + tagName + ">(.*?)<\/" + tagName + ">", 'm');
			var m = re.exec(remaining);
			while (m)
			{
				ret[ret.length] = new OperaNokia_Child(m[1]);
				var s = "<" + tagName + ">" + m[1] + "</" + tagName + ">";
				remaining = remaining.substr(m.index + s.length);
				m = re.exec(remaining);
			}
			return ret;
		};
}

function GetResponseXML(request)
{
	if (navigator.userAgent.indexOf('N770') > -1)
	{
		return new OperaNokia_Child(request.responseText);
	}
	else 
	{
		return request.responseXML;
	}
}


function Queue()
{
	this._queue = 	new Array();
	
	this._index	=	function()
					{
						for (var n in this._queue)
						{
							return n;
						}
						return -1;
					};
	
	this.push 	= 	function(value)
					{
						this._queue[this._queue.length] = value;
					};
					
	this.pop 	= 	function()
					{
						this._queue[this._index()] = null;
						delete this._queue[this._index()];
					};

	this.front	=	function()
					{
						return this._queue[this._index()];
					};

	this.empty	=	function()
					{
						return this._index() == -1;
					};

	this.size	=	function()
					{
						var c = 0;
						for(var n in this._queue)
						{
							++c;
						}
						return c;
					};
}


function AsyncRequest(url, ready_function)
{
	this.url 			= url;
	this.ready_function = ready_function;
}

function AsyncRequestQueue()
{
	function StateChangeFunction(that)
	{
		return function() 
			{
				if (that && that.req && that.req.readyState == 4) 
				{
					if (that.req.status == 200)
					{
						var xml = GetResponseXML(that.req);
						if (!that.queue.front() || that.queue.front() == undefined)
						{
							// this is annoying, but not it would seem a bug???
							status_message.Display("queue is empty!!! - " + that.queue.size());
						}
						else
						{
							that.queue.front().ready_function(xml);
							that.queue.pop();
						}
						that._Next();
					} 
					else 
					{
						set_error_state("There was a problem retrieving the XML data:\n" + req.statusText);
					}
				}
			};
	}

	this.req 					=	null;
	this.queue 					=	new Queue();
	
	this.Request 	= 	function(url, ready_function)
						{
							this.queue.push(new AsyncRequest(url, ready_function));
							if (this.queue.size() == 1)
							{	// issue the command straight away : 
								this._Next();
							}
						};
					
	this._Next		= 	function()
						{
							if (!this.queue.empty())
							{
								this.req 					=	null;
								this.req 					=	new XMLHttpRequest();
								this.req.onreadystatechange = 	StateChangeFunction(this);
								// firefox won't call onreadystatechange??? but it does call onload???
								if (navigator.userAgent.indexOf('Firefox') > -1)
								{
									try { this.req.onload = StateChangeFunction(this); } catch(e) { }
								}
								this.req.open("GET", this.queue.front().url, false);
								this.req.send(null);
							}
						};
}

// give IE a proper XMLHttpRequest object
if (window.ActiveXObject && !window.XMLHttpRequest) 
{ 
	window.XMLHttpRequest = function() 
	{ 
		var msxmls = new Array( 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'); 
		for (var i = 0; i < msxmls.length; i++) 
		{ 
			try { 	return new ActiveXObject(msxmls[i]); 	} 
			catch (e) { } 
		} 
		return null; 
	}; 
}