/*
	XMLHttpRequest wrapper.
	Simas Toleikis (c) 2006
	
	TODO: Workaround for Opera caching issue with GET requests
*/

// namespace Ajax
var Ajax = {}

// class Request
Ajax.Request = function() {

	// private:
	var _target = "";
	var _method = "GET";
	var _xhr = null;
	var _request = this;
	var _useCache = false;
	var _data = null;
	var _timeout = 0;
	var _timeoutTimer = null;
	
	var _eventHandler = function() {
		if (!_xhr) return;
		
		switch(_xhr.readyState) {
			// OPEN
			case 1: {
				if (_request.onOpen)
					_request.onOpen();
				break;
			}
			// SENT
			case 2: {
				if (_request.onSend)
					_request.onSend();
				break;
			}
			// RECEIVING/INTERACTIVE
			case 3: {
				if (_request.onProgress)
					_request.onProgress();
				break;
			}
			// LOADED/COMPLETED
			case 4: {
				clearTimeout(_timeoutTimer);
				
				// 200 OK
				if (_xhr.status == 200) {
					if (_request.onLoad)
						_request.onLoad(new Ajax.Response(_xhr, _data));
				}
				// Error
				else if (_request.onError) {
						_request.onError(_xhr.status, _xhr.statusText);
				}
				break;
			}
		}
	}

	// public:
	this.onLoad = null;
	this.onError = null;
	this.onProgress = null;
	this.onOpen = null;
	this.onSend = null;
	this.onTimeout = null;
	
	// setTarget()
	this.setTarget = function(target) {
		if (typeof target == "string" && target.length > 0)
			_target = target;
	}
	
	// getTarget()
	this.getTarget = function() {
		return _target;
	}
	
	// setMethod()
	this.setMethod = function(method) {
		_method = method.toUpperCase();
	}
	
	// getMethod()
	this.getMethod = function() {
		return _method;
	}
	
	// setHeader()
	this.setHeader = function(header, value) {
		if (!_xhr) return;
		_xhr.setRequestHeader(header, value);
	}
	
	// useCache()
	this.useCache = function(flag) {
		if (typeof flag == "boolean")
			_useCache = flag;
	}
	
	// setTimeout()
	this.setTimeout = function(time) {
		_timeout = time;
	}
	
	// setData()
	this.setData = function(data) {
		_data = data;
	}
	
	// abort()
	this.abort = function() {
		if (_xhr) _xhr.abort();
	}
	
	// send()
	this.send = function(data) {
		if (!_xhr) return;
		
		// Proper Content-Type for POST'ed data
		if (_method == "POST")
			_request.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
		
		// Workaround for IE caching issue with GET requests
		if (!_useCache && _method == "GET" && document.uniqueID) { // IE Only
				_request.setHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
		}
		
		// IXMLHttpRequest.send()
		if (data)
			_xhr.send(data);
		else
			_xhr.send(null);
		
		// Request timeout control
		if (_timeout > 0 && _request.onTimeout)
			_timeoutTimer = setTimeout(function () { _xhr.onreadystatechange = function() {}; _request.abort(); _request.onTimeout(); }, _timeout * 1000);
	}
	
	// Constructor code
	if (arguments[0])
		this.setTarget(arguments[0]);
	if (arguments[1])
		this.setMethod(arguments[1]);

	// Create XMLHttpRequest object
	if (window.XMLHttpRequest) {
		// IE7, Gecko 1.0+, Safari 1.2+, Opera 8+
		_xhr = new XMLHttpRequest();
	}
	else if (window.ActiveXObject) {
		// IE5, IE6
		_xhr = new ActiveXObject("Microsoft.XMLHTTP");
	}
	else {
		throw new Error("XMLHttpRequest is not supported.");
	}
	
	// Set XMLHttpRequest event handler
	_xhr.onreadystatechange = _eventHandler;
	
	// IXMLHttpRequest.open()
	_xhr.open(_method, _target, true);
}

// class Response
Ajax.Response = function() {

	// private:
	var _xhr = null;
	var _data = null;
	
	// public:
	
	// getText()
	this.getText = function() {
		return _xhr.responseText;
	}
	
	// getXML()
	this.getXML = function() {
		return _xhr.responseXML;
	}
	
	// isXML()
	this.isXML = function() {
		return (_xhr.responseXML != null);
	}
	
	// getHeader()
	this.getHeader = function(header) {
		return _xhr.getResponseHeader(header);
	}
	
	// getHeaders()
	this.getHeaders = function() {
		return _xhr.getAllResponseHeaders();
	}
	
	// getData()
	this.getData = function() {
		return _data;
	}
	
	// Constructor code
	if (arguments.length > 0 && typeof arguments[0] == "object")
		_xhr = arguments[0];
	if (arguments.length > 1)
		_data = arguments[1];

}
