/* -*- C -*- */

/* --------------------------------------------------------------------
 * Shine: The Become Interactive Client Application Framework
 * @(#) $Id: com.uk.become.shine.request.js 23692 2008-01-16 09:37:47Z mo $
 * --------------------------------------------------------------------
 * Copyright (c) 2006 Become Interactive
 * http://www.becomeinteractive.co.uk
 * All rights reserved.
 * --------------------------------------------------------------------
 * This software is the confidential and proprietary information of
 * Become Interactive ("Confidential Information").
 *
 * You shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement you
 * with the terms of the license agreement you entered into with
 * Become Interactive.
 * --------------------------------------------------------------------
 */

if(typeof com == "undefined") var com = new Object();
if(typeof com.uk == "undefined") com.uk = new Object();
if(typeof com.uk.become == "undefined") com.uk.become = new Object();
if(typeof com.uk.become.shine == "undefined") com.uk.become.shine = new Object();

/**
 * com.uk.become.shine.Request
 *
 * Scripted HTTP requests on demand
 */
com.uk.become.shine.Request = function(method, uri)
{
	var r;
	var progids = [
				   'MSXML2.XMLHTTP.5.0',
				   'MSXML2.XMLHTTP.4.0',
				   'MSXML2.XMLHTTP.3.0',
				   'MSXML2.XMLHTTP',
				   'Microsoft.XMLHTTP'
				   ];
	
	this._method = method;
	this._uri = uri;
	this._req = false;
	this._loaded = false;
	this._rsInterval = false;
	this.onload = false;
	this.onerror = false;
	this.method = false;
	this.throbber = null;
	this.form = null;
	this.params = new Array();
	this.formVars = new Object();
	this._headers = new Object();
	try
		{
			r = new XMLHttpRequest();
			this._req = r;
		}
	catch(e)
		{
			for(i = 0; i < progids.length; i++)
				{
					try
						{
							r = new ActiveXObject(progids[i]);
							this._req = r;
							break;
						}
					catch(e)
						{
						}
				}
		}
	finally
		{
			return this;
		}
}
com.uk.become.shine.Request.prototype.header = function(n, v)
{
	this._headers[n] = v;
}
com.uk.become.shine.Request.prototype._throbOn = function()
{
	if(!this.throbber) return;
	if(typeof this.throbber.shineThrobDepth == 'undefined')
	{
		this.throbber.shineThrobDepth = 0;
	}
	this.throbber.shineThrobDepth++;
	if(typeof this.throbber.throbOn != 'undefined')
	{
		this.throbber.throbOn();
	}
	else
	{
		this.throbber.style.display = 'block';
	}
}
com.uk.become.shine.Request.prototype._throbOff = function()
{
	if(!this.throbber || typeof this.throbber.shineThrobDepth == 'undefined') return;
	if(this.throbber.shineThrobDepth)
	{
		this.throbber.shineThrobDepth--;
	}
	if(!this.throbber.shineThrobDepth)
	{
		if(typeof this.throbber.throbOff != 'undefined')
		{
			this.throbber.throbOff();
		}
		else
		{
			this.throbber.style.display = 'none';
		}
	}
}
com.uk.become.shine.Request.prototype._readyStateChangeHandler = function(Shine, sender, ev, data)
{
	if(sender.readyState == 4)
	{
		window.clearInterval(this._rsInterval);
		if(this._loaded)
		{
			return false;
		}
		this._loaded = true;
		this._throbOff();
		ev = new Object();
		ev.status = sender.status;
		ev.statusText = sender.statusText;
		
		if(sender.status == 200)
		{
			if(this.onload)
			{
				ev.responseXML = sender.responseXML;
				ev.responseText = sender.responseText;
				if(typeof ev.responseXML != 'undefined' && ev.responseXML != null && typeof ev.responseXML.lastChild != 'undefined' && ev.responseXML.lastChild != null && typeof ev.responseXML.lastChild.tagName != 'undefined')
				{
					ev.responseRoot = ev.responseXML.lastChild;
				}
				else
				{
					ev.responseRoot = null;
				}
				this.onload(ev);
			}
			else
			{
				Shine.debug('Request::_readyStateChangeHandler:', 'Success: status = ' + sender.status + ' (' + sender.statusText + ')');
			}
		}
		else
		{
			if(this.onerror)
			{
				this.onerror(ev);
			}
			else
			{
				Shine.debug('Request::_readyStateChangeHandler:', 'Failed: status = ' + sender.status + ' (' + sender.statusText + ')');
			}
		}
	}
}
com.uk.become.shine.Request.prototype.open = function()
{
	var h, payload, hfv, _this = this, uri, d;
	
	if(!this._req)
		{
			Shine.debug('Request:', 'Request object has no XMLHttpRequest (' + this._method + ' ' + this._uri + ')');				
			return false;
		}
	hfv = false;
	payload = '';
	if(this.method)
	{
		this._method = 'POST';
		this.header('Content-Type', 'application/vnd.become.rpc+xml');
		payload = '<?xml version="1.0" encoding="UTF-8" ?>' + "\n";
		payload += '<methodCall>' + "\n";
		payload += ' <methodName>' + this.method + '</methodName>' + "\n";
		payload += '  <params>' + "\n";
		for(h = 0; h < this.params.length; h++)
			{
				payload += '   <param><value>';
				if(typeof this.params[h] == 'number')
					{
						payload += '<i4>' + this.params[h] + '</i4>';
					}
				else if(typeof this.params[h] == 'boolean')
					{
						payload += '<boolean>' + (this.params[h] ? '1' : '0') + '</boolean>';
					}
				else
					{
						payload += '<string>' + this.params[h] + '</string>';
					}
				payload += '</value></param>' + "\n";
			}
		payload += '  </params>' + "\n";
		payload += '</methodCall>' + "\n";
	}
	else
	{
		for(h in this.formVars)
		{
			hfv = true;					
			payload += encodeURIComponent(h) + '=' + encodeURIComponent(this.formVars[h]) + '&';					
		}
		if(this.form)
		{
			hfv = true;
//			Shine.debug('Request:', 'Processing form with ' + this.form.elements.length + ' elements');
			for(i = 0; i < this.form.elements.length; i++)
			{
//				Shine.debug('Request:', 'Processing form element ' + i + ': ' + this.form.elements[i]);
				if(typeof this.form.elements[i].name == 'undefined' ||
					typeof this.form.elements[i].value == 'undefined' ||
					this.form.elements[i].name.length == 0)
				{
					continue;
				}
				if(this.form.elements[i].type == 'radio' || this.form.elements[i].type == 'checkbox')
				{
					if(!this.form.elements[i].checked) continue;
				}
				payload += encodeURIComponent(this.form.elements[i].name) + '=' + encodeURIComponent(this.form.elements[i].value) + '&';
			}
		}
		if(hfv)
		{
			payload = payload.substr(0, payload.length - 1);
			this.header('Content-Type', 'application/x-www-form-urlencoded');
		}
	}
	d = new Date();
	uri = this._uri;
	if(uri.indexOf('?') != -1)
	{
		uri += '&__ts=' + encodeURIComponent(d.getTime());
	}
	else
	{
		uri += '?__ts=' + encodeURIComponent(d.getTime());
	}
//	Shine.debug('Request:', this._method + ' ' + uri);
//	Shine.debug('Request:', payload);
	_this = this;
	_this._req.open(this._method, uri, true);
//	_this._req.onreadystatechange = function() { _this._readyStateChangeHandler(Shine, _this._req, false, false); }
	/* Work around WebKit bug */
	_this._req.setRequestHeader('If-Modified-Since', 'Wed, 15 Nov 1995 00:00:00 GMT');
	for(h in _this._headers)
	{
		_this._req.setRequestHeader(h, _this._headers[h]);
	}
	_this._throbOn();
	if(payload)
	{
		_this._req.send(payload);
	}
	else
	{
		_this._req.send(null);
	}
	this._rsInterval = window.setInterval(function() { _this._readyStateChangeHandler(Shine, _this._req, false, false); }, 50);
}
