(function() { // $Id: phpbridge.js 1314 2010-04-16 23:36:32Z joris $

window.PHPBridge = construct;
PHPBridge.json_encode = json_encode; // value
PHPBridge.prototype._data = {};
PHPBridge.prototype.addData = addData; // variable, data
PHPBridge.prototype.getData = getData;
PHPBridge.prototype.setJSONData = setJSONData; // json
PHPBridge.prototype.getJSONData = getJSONData;
PHPBridge.prototype.setDataByRequest = setDataByRequest; // url, jsonRequest, callback(bridge)
PHPBridge.prototype.isWaitingForResponse = isWaitingForResponse;
PHPBridge.prototype.cancelRequest = cancelRequest;
PHPBridge.prototype._http = null;
PHPBridge.prototype._httpTimer = 0;
PHPBridge.prototype._httpTimerEvent = null;
PHPBridge.prototype._unloadEvent = null;

function construct()
{
	var self = this;
	this._data = {};
	
	this._unloadEvent = function(e)
	{
		self.cancelRequest();
	};
	
	this._httpTimerEvent = function() 
	{
		self._httpTimer = 0;
		self.cancelRequest();
		self._data = null;

		d('ERROR: XMLHttpRequest timed out!');	
	};
}


function addData(variable, data)
{	
	this._data[variable] = data;
}

function getData()
{
	return this._data;
}

function setJSONData(json)
{
	try
	{
		if (window.JSON)
			this._data = JSON.parse(json); //ECMAScript 5
		else
			this._data = eval("("+json+");");
	}
	catch (err)
	{
		this._data = null;
	}
}

function getJSONData()
{
	if (window.JSON)
		return JSON.stringify(this._data);
	else
		return json_encode(this._data);
}

function setDataByRequest(url, jsonRequest, callback, async)
{
	var bridge;
	bridge = this;
	if (async === undefined) async = true;
	
	substr = url.substr(0, 7);
	if (substr != 'http://' && substr != 'https:/')
		d('<phpbridge> Please use full URLs in setDataByRequest'); // relatieve urls kunnen fout gaan als de <base> tag gecached wordt
	
	assert(!bridge._http);
	
	if (this._httpTimer)
	{
		clearTimeout(this._httpTimer);
		this._httpTimer = 0;
	}
	
	if (async)
	{
		window.addEventListener('unload', this._unloadEvent, false);
		this._httpTimer = setTimeout(this._unloadEvent, 15000);
	}
	
	bridge._http = httpRequest(
		url, 
		jsonRequest, 
		function(responseText)
		{
			bridge._http = null;
			if (bridge._httpTimer)
			{
				clearTimeout(bridge._httpTimer);
				bridge._httpTimer = 0;
			}
			window.removeEventListener('unload', bridge._unloadEvent, false);
			
			if (responseText)
				bridge.setJSONData(responseText);
			else
				bridge._data = null;
			
			if (callback)
				callback(bridge);
		},
		async)
		;
}

function isWaitingForResponse()
{
	return !!this._http;
}

function cancelRequest()
{
	if (this._http)
	{
		if (this._http.readyState == 1 || this._http.readyState == 2 || this._http.readyState == 3)
		{
			this._http.abort();
		}
		
		if (this._httpTimer)
		{
			clearTimeout(this._httpTimer);
			this._httpTimer = 0;
		}
		this._http = null;
	}
	
	window.removeEventListener('unload', this._unloadEvent, false);
}


function httpRequest(url, jsondata, callback, async) 
{
	var http, param, sep;
	var self = this;
	http = getHTTPObject();
	
	if (async === undefined) async = true;
	
	http.open('POST', url, async);
	http.setRequestHeader('Content-Type', 'application/json; charset="UTF-8"');
	//http.setRequestHeader('Accept-Charset', 'UTF-8');
	//http.setRequestHeader('Connection', 'close'); // ignored, but whatever
	http.setRequestHeader('X-RMREQUESTTOKEN', rmdata.auth.requestToken);
	
	if (async)
		http.onreadystatechange = function() { handleHttpResponse(http, callback) }; 
	
	if (jsondata == null)
	{
		//http.setRequestHeader("Content-length", 0);
		http.send(null);
	}
	else 
	{
		//http.setRequestHeader("Content-length", binarySize_UTF8(jsondata));
		http.send(jsondata);
	}
	
	if (!async)
	{
		handleHttpResponse(http, callback);
	}
	
	return http;
}

function handleHttpResponse(http, callback) 
{
	var statusText;
	if (http.readyState == 4) 
	{	
	  	if (http.status == 200) 
		{
			callback(http.responseText);
	        }
		else 
		{
			try
			{
				statusText = http.statusText;
			}
			catch (err)
			{
				statusText = "unable to retreive statusText"; 
			}
			
			d('Error in XMLHTTPRequest response: %d (%s)', http.status, statusText);
			callback(false);
	        }
	}
}

function getHTTPObject() 
{
	var xmlhttp;
	/*@cc_on
	@if (@_jscript_version >= 5)
		try {
			xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (E) {
				xmlhttp = null;
			}
		}
	@else
		xmlhttp = false;
	@end @*/
	if (!xmlhttp && XMLHttpRequest !== undefined) 
	{
		try
		{
			xmlhttp = new XMLHttpRequest();
		}
		catch (e) 
		{
			xmlhttp = null;
		}
	}
	
	return xmlhttp;
}

var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
var meta = {    // table of character substitutions
	'\b': '\\b',
	'\t': '\\t',
	'\n': '\\n',
	'\f': '\\f',
	'\r': '\\r',
	'"' : '\\"',
	'\\': '\\\\'
};

function json_quote(string) 
{ // http://www.json.org/json2.js
	// If the string contains no control characters, no quote characters, and no
	// backslash characters, then we can safely slap some quotes around it.
	// Otherwise we must also replace the offending characters with safe escape
	// sequences.
	
	escapable.lastIndex = 0;
	return escapable.test(string) ?
	'"' + string.replace(escapable, function (a) {
	var c = meta[a];
	return typeof c === 'string' ? c :
	'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
	}) + '"' :
	'"' + string + '"';
}


function json_encode(value) 
{
	var a, len, str, sep;
	
	switch (typeof value)
	{
		case 'string':
			return json_quote(value);
		
		case 'number':
			return isFinite(value) ? String(value) : 'null';
		
		case 'boolean':
        	case 'null':
			return String(value);
		
	        case 'object':

			// Due to a specification blunder in ECMAScript, typeof null is 'object',
			// so watch out for that case.

			if (!value) 
				return 'null';
	            
			if (value instanceof Array) // []
			{
				str = '[';
				for (a = 0, len = value.length; a < len; a++)
				{
					str += json_encode(value[a]);
					if (a < len-1)
						str += ',';
				}
				return str + ']';
			}
			else // {}
			{
				str = '{';
				sep = '';
				
				for (a in value)
				{
					if (!value.hasOwnProperty(a))
						continue;
					
					str += sep + json_quote(a) + ':' + json_encode(value[a]);
					sep = ','
				}
				
				return str + '}';
			}		
	}
	return 'null';
}



})();
