var READY_STATE_UNINITIALIZED = 0;
var READY_STATE_LOADING       = 1;
var READY_STATE_LOADED        = 2;
var READY_STATE_INTERACTIVE   = 3;
var READY_STATE_COMPLETE      = 4;

window.XMLHTTPRequest = 
{
	to: 3000, //Must Be Greater Than 0
	xhr: null,
	timer_id: 0,
	callback_owner: null,
	callback_onreadystatechange: null,
	callback_timeout: null,
	
	newXMLHttpRequest: function()
	{
		if(this.xhr != null)
		{
			return true;
		}

		if(window.XMLHttpRequest)
		{
      		this.xhr = new XMLHttpRequest();
   		}
		else if(typeof ActiveXObject != "undefined")
		{
			this.xhr = new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		return (XMLHTTPRequest.xhr != null);
	},
	onTimeOut: function()
	{
		if(XMLHTTPRequest.xhr == null)
		{
			return;
		}

		clearTimeout(XMLHTTPRequest.timer_id);
		XMLHTTPRequest.timer_id = 0;
				
		XMLHTTPRequest.xhr.abort();

		if(typeof XMLHTTPRequest.callback_timeout == "function")
		{
			XMLHTTPRequest.callback_timeout.apply(XMLHTTPRequest.callback_owner);
		}
		else
		{
			/* Default Handler */ 
			alert('timeout for waiting responseXML');
		}

		XMLHTTPRequest.callback_owner = null;
		XMLHTTPRequest.callback_onreadystatechange = null;
		XMLHTTPRequest.callback_timeout = null;

		if(Browser.IE)
		{
			/* Clean Up for IE's Memory Leak */
			delete XMLHTTPRequest.xhr["onreadystatechange"];
			delete XMLHTTPRequest.xhr;
		}
	},
	onReadyStateChange: function()
	{
		var ready = XMLHTTPRequest.xhr.readyState;

		if(ready == READY_STATE_COMPLETE)
		{
			if(XMLHTTPRequest.timer_id == 0)
			{
				return; /*Time Out*/
			}

			clearTimeout(XMLHTTPRequest.timer_id);
			XMLHTTPRequest.timer_id = 0;
					
			if(typeof XMLHTTPRequest.callback_onreadystatechange == "function")
			{
				if(Browser.IE || Browser.Gecko || Browser.Opera)
				{
					XMLHTTPRequest.callback_onreadystatechange.call(XMLHTTPRequest.callback_owner, ready, XMLHTTPRequest.xhr.responseXML);
				}
				else
				{
					/* Not Implemented */
				}
			}
			
			XMLHTTPRequest.callback_owner = null;
			XMLHTTPRequest.callback_onreadystatechange = null;
			XMLHTTPRequest.callback_timeout = null;
//			delete XMLHTTPRequest.__XMLREQUEST__["onreadystatechange"];
//			delete XMLHTTPRequest.__XMLREQUEST__;
			if(Browser.IE)
			{
				/* Clean Up for IE's Memory Leak */
				delete XMLHTTPRequest.xhr["onreadystatechange"];
				delete XMLHTTPRequest.xhr;
			}
		}
		else
		{
			if(typeof XMLHTTPRequest.callback_onreadystatechange == "function")
			{
				XMLHTTPRequest.callback_onreadystatechange.call(XMLHTTPRequest.callback_owner, ready, null);
			}
		}
	},
	sendRequest: function(url, params, method, bAsync, widget, callbackOnReadyStateChange, callbackTimeOut, to)
	{
		if(false == this.newXMLHttpRequest())
		{
			return false;
		}
 
 		this.callback_owner = (widget == null) ? window : widget;
		this.callback_onreadystatechange = callbackOnReadyStateChange;
		this.timer_id = setTimeout(this.onTimeOut, ( (to == null) ? this.to : to) );
   		this.callback_timeout = callbackTimeOut;

		if(bAsync == true)
		{
			this.xhr.onreadystatechange = this.onReadyStateChange;
		}
		//Sending
		if(Browser.IE)
		{
			this.xhr.open(method, url, bAsync);
			this.xhr.setRequestHeader("Content-Type", method == 'POST' ? "application/x-www-form-urlencoded;" : "text/xml");
			/* IE Cache Bug for GET Request */
			this.xhr.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
			this.xhr.send(params);		
		}
		else if(Browser.Gecko || Browser.Opera)
		{
			this.xhr.open(method, url, bAsync);
			//this.xml_request.overrideMimeType('text/xml');
			this.xhr.send(null);
		}
		else
		{
		}		  
 		
		//Return result
		if(bAsync == false)
		{
			clearTimeout(XMLHTTPRequest.timer_id);
			XMLHTTPRequest.timer_id = 0;
					
			if(typeof XMLHTTPRequest.callback_onreadystatechange == "function" && XMLHTTPRequest.callback_handler != null)
			{
				XMLHTTPRequest.callback_onreadystatechange.call(XMLHTTPRequest.callback_handler, XMLHTTPRequest.xhr.responseXML);
			
				XMLHTTPRequest.callback_handler = null;
				XMLHTTPRequest.callback_onreadystatechange = null;
				XMLHTTPRequest.callback_timeout = null;		
				delete XMLHTTPRequest.xhr["onreadystatechange"];
				delete XMLHTTPRequest.xhr;
				
				return true;
			}
			else
			{
				var xmlDoc = this.xhr.responseXML;
				this.callback_timeout = null;		
				delete XMLHTTPRequest.xhr;
				return xmlDoc;
			}
		}
	}
}


window.XMLHTTPREQUEST_WIDGET = null;
window.XMLHTTPREQUEST_TIMEOUT = 3000;
window.XMLHTTPREQUEST_HANDLER_ID = null;

function XMLHTTPREQUEST_ASYNCMAP(id, handler_name)
{
	window["xmlhandler_" + id] = handler_name;
}

window.onXMLLoad = function(ready, xmlDocument)
{
	if(ready == READY_STATE_COMPLETE)
	{
		this["XMLHTTPREQUEST_WIDGET"][this["xmlhandler_" + this["XMLHTTPREQUEST_HANDLER_ID"]]](xmlDocument);
		this["XMLHTTPREQUEST_WIDGET"] = null;
		this["XMLHTTPREQUEST_HANDLER_ID"] = null;
	}

	this.onXMLLoadStatus(ready);
}

window.onXMLLoadTimeOut = function()
{
	if(this["XMLHTTPREQUEST_WIDGET"] != this && typeof this["XMLHTTPREQUEST_WIDGET"]["onHttpRequestTimeOut"] == "function")
	{
		this["XMLHTTPREQUEST_WIDGET"]["onHttpRequestTimeOut"]();
	}
	this["XMLHTTPREQUEST_WIDGET"] = null;
	this["XMLHTTPREQUEST_HANDLER_ID"] = null;
}

window.onXMLLoadStatus = function(ready)
{
}

window.sendRequest = function()
{
	if(arguments.length < 3 || this["XMLHTTPREQUEST_HANDLER_ID"] != null || this["XMLHTTPREQUEST_WIDGET"] != null )
	{
		return;
	}

	var widget = (arguments[0] == null) ? window : arguments[0];
	var id     = arguments[1];
	var url    = arguments[2];
	var param  = (arguments[3] == null) ? null : arguments[3];
	var method = (arguments[4] == null) ? "GET" : arguments[4].toUpperCase();
	
	//Not Binding
	if(typeof widget[this["xmlhandler_"+id]] != "function")
	{
		return;
	}

	this["XMLHTTPREQUEST_WIDGET"] = widget;
	this["XMLHTTPREQUEST_HANDLER_ID"] = id;
	
	XMLHTTPRequest.sendRequest(url, param, method, true, this, this.onXMLLoad, this.onXMLLoadTimeOut, window.XMLHTTPREQUEST_TIMEOUT);
}

function $xpathNodes(baseNode, path)
{
	if(Browser.IE)
	{
		return baseNode.selectNodes(path);
	}
	else if(Browser.Gecko || Browser.Opera)
	{
//		var oEvaluator = new XPathEvaluator();
		if(nsResolver == null)
		{
			nsResolver = oEvaluator.createNSResolver(baseNode.ownerDocument == null ? baseNode.documentElement : baseNode.ownerDocument.documentElement);
		}
		
//		var oResult = oEvaluator.evaluate(path, baseNode, nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
		var oResult = baseNode.ownerDocument.evaluate(path, baseNode, nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
		var aNodes = [];

		var oElement;
		while(oElement = oResult.iterateNext())
		{
			aNodes.push(oElement);
		}
		
		return aNodes;
	}

	return null;
}

function $xpathNode(baseNode, path)
{
	if(Browser.IE)
	{
		return baseNode.selectSingleNode(path);
	}
	else if(Browser.Gecko || Browser.Opera)
	{
		//var oEvaluator = new XPathEvaluator();
		if(nsResolver == null)
		{
			nsResolver = oEvaluator.createNSResolver(baseNode.ownerDocument == null ? baseNode.documentElement : baseNode.ownerDocument.documentElement);
		}
		
		var oResult = baseNode.ownerDocument.evaluate(path, baseNode, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

		return (oResult != null) ? oResult.singleNodeValue : null;
	}
	
	return null;
}