/**
 * XMLHttpRequest Iframe fallback
 *
 * http://lxr.mozilla.org/seamonkey/source/extensions/xmlextras/tests/ - should work with these
 *
 * @category	HTML
 * @package	AJAX
 * @author	Elizabeth Smith <auroraeosrose@gmail.com>
 * @copyright 	2005 Elizabeth Smith
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 */
HTML_AJAX_IframeXHR_instances = new Object();
function HTML_AJAX_IframeXHR()
{
	this._id = 'HAXHR_iframe_' + new Date().getTime();
	HTML_AJAX_IframeXHR_instances[this._id] = this;
}
HTML_AJAX_IframeXHR.prototype = {
// Data not sent with text/xml Content-Type will only be available via the responseText property

	// properties available in safari/mozilla/IE xmlhttprequest object
	onreadystatechange: null, // Event handler for an event that fires at every state change
	readyState: 0, // Object status integer: 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete
	responseText: '', // String version of data returned from server process
	responseXML: null, // DOM-compatible document object of data returned from server process
	status: 0, // Numeric code returned by server, such as 404 for "Not Found" or 200 for "OK"
	statusText: '', // String message accompanying the status code
	iframe: true, // flag for iframe

	//these are private properties used internally to keep track of stuff
	_id: null, // iframe id, unique to object(hopefully)
	_url: null, // url sent by open
	_method: null, // get or post
	_async: null, // sync or async sent by open
	_headers: new Object(), //request headers to send, actually sent as form vars
	_response: new Object(), //response headers received
	_phpclass: null, //class to send
	_phpmethod: null, //method to send
	_history: null, // opera has to have history munging

	// Stops the current request
	abort: function()
	{
		var iframe = document.getElementById(this._id);
		if (iframe) {
			document.body.removeChild(iframe);
		}
		if (this._timeout) {
			window.clearTimeout(this._timeout);
		}
		this.readyState = 1;
		if (typeof(this.onreadystatechange) == "function") {
			this.onreadystatechange();
		}
	},

	// This will send all headers in this._response and will include lastModified and contentType if not already set
	getAllResponseHeaders: function()
	{
		var string = '';
		for (i in this._response) {
			string += i + ' : ' + this._response[i] + "\n";
		}
		return string;
	},

	// This will use lastModified and contentType if they're not set
	getResponseHeader: function(header)
	{
		return (this._response[header] ? this._response[header] : null);
	},

	// Assigns a label/value pair to the header to be sent with a request
	setRequestHeader: function(label, value) {
		this._headers[label] = value;
		return; },

	// Assigns destination URL, method, and other optional attributes of a pending request
	open: function(method, url, async, username, password)
	{
		if (!document.body) {
			throw('CANNOT_OPEN_SEND_IN_DOCUMENT_HEAD');
		}
		//exceptions for not enough arguments
		if (!method || !url) {
			throw('NOT_ENOUGH_ARGUMENTS:METHOD_URL_REQUIRED');
		}
		//get and post are only methods accepted
		this._method = (method.toUpperCase() == 'POST' ? 'POST' : 'GET');
		this._decodeUrl(url);
		this._async = async;
		if(!this._async && document.readyState && !window.opera) {
			throw('IE_DOES_NOT_SUPPORT_SYNC_WITH_IFRAMEXHR');
		}
		//set status to loading and call onreadystatechange
		this.readyState = 1;
		if(typeof(this.onreadystatechange) == "function") {
			this.onreadystatechange();
		}
	},

	// Transmits the request, optionally with postable string or DOM object data
	send: function(content)
	{
		//attempt opera history munging
		if (window.opera) {
			this._history = window.history.length;
		}
		//create a "form" for the contents of the iframe
		var form = '<html><body><form method="'
			+ (this._url.indexOf('px=') < 0 ? this._method : 'post')
			+ '" action="' + this._url + '">';
		//tell iframe unwrapper this IS an iframe
		form += '<input name="Iframe_XHR" value="1" />';
		//class and method
		if (this._phpclass != null) {
			form += '<input name="Iframe_XHR_class" value="' + this._phpclass + '" />';
		}
		if (this._phpmethod != null) {
			form += '<input name="Iframe_XHR_method" value="' + this._phpmethod + '" />';
		}
		// fake headers
		for (label in this._headers) {
			form += '<textarea name="Iframe_XHR_headers[]">' + label +':'+ this._headers[label] + '</textarea>';
		}
		// add id
		form += '<textarea name="Iframe_XHR_id">' + this._id + '</textarea>';
		if (content != null && content.length > 0) {
			form += '<textarea name="Iframe_XHR_data">' + content + '</textarea>';
		}
		form += '<input name="Iframe_XHR_HTTP_method" value="' + this._method + '" />';
		form += '<s'+'cript>document.forms[0].submit();</s'+'cript></form></body></html>';
		form = "javascript:document.write('" + form.replace(/\'/g,"\\'") + "');void(0);";
		this.readyState = 2;
		if (typeof(this.onreadystatechange) == "function") {
			this.onreadystatechange();
		}
		// try to create an iframe with createElement and append node
		try {
			var iframe = document.createElement('iframe');
			iframe.id = this._id;
			// display: none will fail on some browsers
			iframe.style.visibility = 'hidden';
			// for old browsers with crappy css
			iframe.style.border = '0';
			iframe.style.width = '0';
			iframe.style.height = '0';
			
			if (document.all) {
				// MSIE, opera
				iframe.src = form;
				document.body.appendChild(iframe);
			} else {
				document.body.appendChild(iframe);
				iframe.src = form;
			}
		} catch(exception) {
			// dom failed, write the sucker manually
			var html = '<iframe src="' + form +'" id="' + this._id + '" style="visibility:hidden;border:0;height:0;width:0;"></iframe>';
			document.body.innerHTML += html;
		}
		if (this._async == true) {
			//avoid race state if onload is called first
			if (this.readyState < 3) {
				this.readyState = 3;
				if(typeof(this.onreadystatechange) == "function") {
					this.onreadystatechange();
				}
			}
		} else {
			//we force a while loop for sync, it's ugly but hopefully it works
			while (this.readyState != 4) {
				//just check to see if we can up readyState
				if (this.readyState < 3) {
					this.readyState = 3;
					if(typeof(this.onreadystatechange) == "function") {
						this.onreadystatechange();
					}
				}
			}
		}
	},

	// attached as an onload function to the iframe to trigger when we're done
	isLoaded: function(headers, data)
	{
		this.readyState = 4;
		//set responseText, Status, StatusText
		this.status = 200;
		this.statusText = 'OK';
		this.responseText = data;
		this._response = headers;
		if (!this._response['Last-Modified']) {
			string += 'Last-Modified : ' + document.getElementById(this._id).lastModified + "\n";
		}
		if (!this._response['Content-Type']) {
			string += 'Content-Type : ' + document.getElementById(this._id).contentType + "\n";
		}
		// if this is xml populate responseXML accordingly
		if (this._response['Content-Type'] == 'application/xml')
		{
			return new DOMParser().parseFromString(this.responseText, 'application/xml');
		}
		//attempt opera history munging in opera 8+ - this is a REGRESSION IN OPERA
		if (window.opera && window.opera.version) {
			//go back current history - old history
			window.history.go(this._history - window.history.length);
		}
		if (typeof(this.onreadystatechange) == "function") {
			this.onreadystatechange();
		}
		document.body.removeChild(document.getElementById(this._id));
	},

	// strip off the c and m from the url send...yuck
	_decodeUrl: function(querystring)
	{
		//opera 7 is too stupid to do a relative url...go figure
		var url = unescape(location.href);
		url = url.substring(0, url.lastIndexOf("/") + 1);
		var item = querystring.split('?');
		//rip off any path info and append to path above <-  relative paths (../) WILL screw this
		this._url = url + item[0].substring(item[0].lastIndexOf("/") + 1,item[0].length);
		if(item[1]) {
			item = item[1].split('&');
			for (i in item) {
				var v = item[i].split('=');
				if (v[0] == 'c') {
					this._phpclass = v[1];
				} else if (v[0] == 'm') {
					this._phpmethod = v[1];
				}
			}
		}
		if (!this._phpclass || !this._phpmethod) {
			var cloc = window.location.href;
			this._url = cloc + (cloc.indexOf('?') >= 0 ? '&' : '?') + 'px=' + escape(HTML_AJAX_Util.absoluteURL(querystring));
		}
	}
}
