/**
 * HTMLRequest v2
 * -----------
 *
 * Home of this script is http://blog.underconstruction.hu/ and
 * can be downloaded from http://blog.underconstruction.hu/scripts/HTTPRequest/HTTPRequest2.js
 *
 * @author Adam Brunner <adambrunner-at-underconstruction.hu>
 * @copyright 2005-2006. underconstruction.hu
 * @version 2.0.4
 * @licence Creative Commons 2.5 Attribution-NoDerivs http://creativecommons.org/licenses/by-nd/2.5/
 *
 * Attribute me (Adam Brunner @ blog.underconstruction.hu) in the impressum, or other place
 * on the site and don't remove this comment!
 *
 * Parameters
 * ----------
 *
 * readonly string version
 *          Returns the actual version of the class.
 * boolean  debug
 *          If true, an alert will be shown is some error occures.
 * @todo function onstart
 *          Set it to a function and will be evulate just at the start of the 'send()' method
 * @todo function onend
 *          Set it to a function and will be evulate just at the end of the 'send()' method
 *
 * Methods
 * -------
 *
 * mixed   HTTPRequest ( [string action], [POST,GET method], [object parameters], [Text,XML,JSON returnMode], [boolean sendNow] )
 *         Constructor.
 * string  setReturnMode ( [string returnMode] )
 *         Can be Text, XML or JSON. Returns the previous value.
 * string  setMethod ( [string method] )
 *         Sets the method of the post to POST or GET. Default is GET.
 *         Returns the previous state.
 * string  setAction ( [string action] )
 *         Sets the URL to specified, where the data will be sent. Returns previous action.
 * boolean add ( string name, string value )
 *         Adds a parameter to the data pool, with given name and value.
 * boolean addParameters ( hash parameters )
 *         Adds all of values in the given hash to the data pool. The post variable name will be the key of the hash.
 * mixed   send ( [hash parameters] )
 *         Adds parameters to the data pool.
 *         Returns the response from the server (if was)
 * void    setToDefault ( )
 *         Sets all property to default.
 * boolean wasError ( )
 *         Returns TRUE if any error occured during the process (reset() sets this to false)
 * string  errorMsg ( )
 *         Returns the last error message if was.
 *
 * Example
 * -------
 *
 *     var myRequest = new HTTPRequest();
 *     myRequest.setMethod('POST'); //default is GET
 *     myRequest.setAction('http://www.example.com/index.php'); //the URL where to send the data
 *     myRequest.setReturnMode('text'); //default is XML
 *     //Equal with myRequest.addParams({'variableName1':'value1','variableName2':'value2'});
 *     myRequest.add('variableName1','value1');
 *     myRequest.add('variableName2','value2');
 *     var response = myRequest.send();
 *     if(!myRequest.wasError()) {
 *         //do something with response
 *     } else {
 *         alert(myRequest.errorMsg());
 *     }
 *
 *     OR
 *
 *     var response = new HTTPRequest('http://www.example.com/index.php','POST',{'variableName1':'value1','variableName2':'value2'},'text',true);
 */

if(typeof(browser) == 'undefined') {
	var browser = {
		isIE: navigator.userAgent.toLowerCase().indexOf("msie")>-1 && navigator.userAgent.toLowerCase().indexOf("opera")==-1,
		isOpera: navigator.userAgent.toLowerCase().indexOf("opera")>-1,
		isGecko: navigator.userAgent.toLowerCase().indexOf("gecko")>-1,
		isSafari: navigator.userAgent.toLowerCase().indexOf("safari")>-1
	};
}

/**
 * @return object Returns an HTTPRequest object
 */
var HTTPRequest = function (a_action, a_method, a_params, a_returnMode, a_sendNow) {
	this.version = '2.0.4';
	this.debug = false;
	//this.onstart = function() {};
	//this.onstop = function() {};

	this.wasError = function() {
		return (_lastErrorMsg);
	};

	this.errorMsg = function() {
		ret = _lastErrorMsg;
		_lastErrorMsg = '';
		return ret;
	};

	this.setReturnMode = function(__returnMode) {
		var _ret = _returnMode;
		try
		{
			switch(__returnMode.toUpperCase()) {
				case 'JSON':
				case 'TEXT':
				case 'XML':
					_returnMode = __returnMode.toUpperCase();
					break;
			}
		}
		catch(e) {}
		finally {
			return _ret;
		}
	};

	this.setMethod = function(__method) {
		var _ret = _method;

		try
		{
			switch(__method.toUpperCase()) {
				case 'POST':
				case 'GET':
					_method = __method.toUpperCase();
					break;
			}
		}
		catch(e) {}
		finally {
			return _ret;
		}
	};

	this.setAction = function(__action) {
		if(__action == '') {
			_error('No action was specified!');
			return '';
		}
		_ret = _action
		_action = __action;
		return _ret;
	};

	this.add = function(_name, _value) {
		if(typeof(_value) == 'function') { return false; }

		if(typeof(_value) == 'object') {
			var i;
			for(i in _value) {
				this.add(_name+'['+i+']',_value[i]);
			}
			return true;
		}

		if(!_name) {
			_error('No name was specified to the parameter!');
			return false;
		}
		
		_params[_params.length] = {
			name: _name,
			value: _value
		};
		return true;
	};

	this.addParameters = function(_parameterArray) {
		if(typeof(_parameterArray) != 'object') { return false; }
		for(var i in _parameterArray) {
			this.add(i, _parameterArray[i]);
		}
		return true;
	};

	this.send = function() {
		if(arguments.length && arguments[0])  {
			this.addParameters(arguments[0]);
		}

		//if(this.onstart) { this.onstart(); }

		var ret = null;

		var httpRequest;
		try {
			httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (oc) {
				httpRequest = null;
			}
		}

		if(!httpRequest && typeof XMLHttpRequest != "undefined") {
			httpRequest= new XMLHttpRequest();
		}

		if(!httpRequest) {
			_error('Error creating the connection!');
			return false;
		}

		try {
			var txt = [];
			for(var i in _params) {
				txt[txt.length] = escape(_params[i].name)+'='+escape(_params[i].value);
			}

			_host = _action+(_action.indexOf('?')==-1?'?':'&')+txt.join('&');
			_realHost = _host.substr(0,_host.indexOf('?'));
			_post = _host.substr(_host.indexOf('?')+1);

			switch(_method) {
				case 'POST':
					httpRequest.open("POST", _realHost, false, null, null);  
					if(!browser.isOpera) {
						// Why Opera don't know this?
						httpRequest.setRequestHeader("content-type","application/x-www-form-urlencoded");
					}
					httpRequest.send(_post);
					break;
				default:
					httpRequest.open("GET", _realHost+(_post?'?'+_post:''), false, null, null);  
					httpRequest.send(null);
					break;
			}
		} catch (e) {
			_error('An error has occured calling the external site: '+e);
			return ret;
		} 
	
		switch(httpRequest.readyState) {
			case 1,2,3:
				_error('Bad Ready State: '+httpRequest.status);
				break;
			case 4:
				if(httpRequest.status != 200) {
					_error('The server respond with a bad status code: '+httpRequest.status);
					break;
				} else {
					switch(_returnMode) {
						case 'JSON':
							try {
								ret = eval('('+httpRequest.responseText+')');
							} catch(e) {
								ret = null;
								_error('Returned invalid JSON object');
							}
							break;
						case 'TEXT':
							ret = httpRequest.responseText;
							break;
						case 'XML':
						default:
							ret = httpRequest.responseXML;
							break;
					}
					this.setToDefault();
				}
				break;
			default:
				_error('Unknown readyState code returned!');
				break;
		}

		//if(this.onstop) { this.onstop(); }

		return ret;
	};

	this.setToDefault = function() {
		_params = [];
		_action = null;
		_method = 'GET';
		_host = '';
		_realHost = '';
		_post = '';
		_lastErrorMsg = '';
		_returnMode = 'XML';
		this.onstart = function() {};
		this.onend = function() {};
		return null;
	};

	var _params = [];
	var _action = null;
	var _method = 'GET';
	var _host = '';
	var _realHost = '';
	var _post = '';
	var _returnMode = 'XML';

	var _error = function(__errMsg) {
		if(this.debug) { alert(__errMsg); }
		_lastErrorMsg = __errMsg;
		return;
	}
	
	switch(true) {
		case arguments.length >= 4: this.setReturnMode(a_returnMode);
		case arguments.length >= 3: this.addParameters(a_params);
		case arguments.length >= 2: this.setMethod(a_method);
		case arguments.length >= 1: this.setAction(a_action);
	}

	if(a_sendNow) {
		return this.send();
	}
}

