var Cathmhaol = window.Cathmhaol || {};

/**
* @library     Cathmhaol.Ajax
* @description Creates an XHR object.
* @author      Robert King
*
* @example     var oAjax = new Cathmhaol.Ajax(); oAjax.post("http://www.cathmhaol.com/license/index.asp", true, document.forms[0]);
*/
Cathmhaol.Ajax = function() {
	this._initialize();
};

Cathmhaol.Ajax.prototype = {
	/**
	* @property    ASYNC
	* @description Indicates if the request is to be asynchronous or not
	* @type {boolean}
	* @default "false"
	*/
	ASYNC: false,

	/**
	* @method      displayError
	* @description Displays an error message in the window status bar
	* @returns {boolean}
	*/
	displayError: function(errorMessage) {
		window.status = errorMessage;
		return true;
	},

	/**
	* @method      displayState
	* @description Displays the session state in the window status bar
	* @returns {boolean}
	*/
	displayState: function() {
		window.status = "AJAX Session State: "+this._READY_STATE_CODES[this.readyState()];
		return true;
	},

	/**
	* @method      displayStatus
	* @description Displays the session status in the window status bar
	* @returns {boolean}
	*/
	displayStatus: function() {
		window.status = "AJAX Session HTTP Status: "+this._HTTP_STATUS_CODES[this.status()];
		return true;
	},

	/**
	* @method      open
	* @description Opens an XHR session
	* @returns {void}
	* @param {string} uri     URL to use
	* @param {boolean} async  Request should be asynchronous
	*/
	open: function(uri, async) {
		try {
			if (async) { this.ASYNC = async; }
			if (uri) { this.URL = uri; }

			this.RequestObject.open("get", this.URL, this.ASYNC);
			try {
				this.setRequestHeader("Content-Type","text/xml");
				this.setRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate");
				if (this.RequestObject.overrideMimeType) this.RequestObject.overrideMimeType("text/xml");
				try {
					this.RequestObject.send(null);
				} catch (e) {
					this.displayError("Unable to retrieve data");
				}
			} catch (e) {
				this.displayError("Unable to initialize XMLHttpRequest object");
			}
		} catch (e) {
			this.displayError("Unable to open XMLHttpRequest object");
		}
		return;
	},

	/**
	* @method      post
	* @description Opens an XHR session and posts the form
	* @returns {void}
	* @param {string} uri       URL to use
	* @param {boolean} async    Request should be asynchronous
	* @param {node} formObject  The DOM node that is the form to be posted
	*/
	post: function(uri, async, formObject) {
		var url = uri.split("?")[0];
		var query = uri.split("?")[1];
		query = (query) ? query.split("&") : new Array();
		for (var i = 0; i < formObject.elements.length; i++) {
			field = formObject.elements[i];
			name = encodeURIComponent(field.name);

			if (field.disabled || typeof(field.type) == 'undefined') {
				continue;
			}
			switch (field.type.toLowerCase()) {
				case "radio":
				case "checkbox":
					if (field.checked) {
						value = field.value || "on";
						query.push(name +"="+ encodeURIComponent(value));
					}
					break;
				case "select-one":
				case "select-multiple":
					options = field.options;
					for (var n = 0; n < options.length; n++) {
						if (options[n].selected) {
							value = options[n].value || options[n].text;
							query.push(name +"="+ encodeURIComponent(value));
						}
					}
					break;
				case "text":
				case "textarea":
				case "hidden":
				case "password":
				case "button":
				case "submit":
					query.push(name +"="+ encodeURIComponent(field.value));
					break;
				default: // button, submit, etc.
					break;
			}
		}
		query.push("cache_buster="+ Math.random().toString());
		query = query.join("&");

		try {
			this.RequestObject.open("POST", url, async);
			try {
				this.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
				this.setRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate");
				if (this.RequestObject.overrideMimeType) this.RequestObject.overrideMimeType("text/xml");
				try {
					this.RequestObject.send(query);
				} catch (e) {
					this.displayError("Unable to retrieve data");
				}
			} catch (e) {
				this.displayError("Unable to initialize XMLHttpRequest object");
			}
		} catch (e) {
			this.displayError("Unable to open XMLHttpRequest object");
		}
		return;
	},

	/**
	* @method      readyState
	* @description Returns the ready state of the XHR object
	* @returns {integer}
	*/
	readyState: function() {
		return this.RequestObject.readyState;
	},

	/**
	* @property    RequestObject
	* @description The XHR object
	* @type {XmlHttpRequest}
	*/
	RequestObject: null,

	/**
	* @method      setRequestHeader
	* @description Sets the specified header to the specified value
	* @returns {void}
	* @param {string} header  Header to be set
	* @param {string} value   Value to use for the header
	*/
	setRequestHeader: function(header, value) {
		this.RequestObject.setRequestHeader(header, value);
		return;
	},

	/**
	* @method      status
	* @description Returns the status of the XHR object session
	* @returns {integer}
	*/
	status: function() {
		return this.RequestObject.status;
	},

	/**
	* @property    URL
	* @description The URL for the AJAX request
	* @type {string}
	*/
	URL: null,

	/**
	* @private
	* @property    _MSXML_OBJECT_TYPES
	* @description MS XMLHTTP object types
	* @type {string[]}
	*/
	_MSXML_OBJECT_TYPES: new Array("MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"),

	/**
	* @private
	* @property    _MSXML_TYPE
	* @description MS XMLHTTP object type index
	* @type {integer}
	*/
	_MSXML_TYPE: -1,

	/**
	* @private
	* @property    _READY_STATE_CODES
	* @description Enum for the XHR state
	* @type {string[]}
	*/
	_READY_STATE_CODES: new Array("Uninitialized", "Loading", "Loaded", "Interactive", "Complete"),

	/**
	* @private
	* @property    _HTTP_STATUS_CODES
	* @description Enum for the HTTP status codes
	* @type {string[]}
	*/
	_HTTP_STATUS_CODES: new Array(),

	/**
	* @private
	* @method      _initialize
	* @description Initializes the HTTP status codes and creates an XHR object.
	* @returns {XmlHttpRequest}
	*/
	_initialize: function() {
		this._HTTP_STATUS_CODES['200'] = "OK";
		this._HTTP_STATUS_CODES['201'] = "Created";
		this._HTTP_STATUS_CODES['202'] = "Accepted";
		this._HTTP_STATUS_CODES['203'] = "Non-Authoritative Information";
		this._HTTP_STATUS_CODES['204'] = "No Content";
		this._HTTP_STATUS_CODES['205'] = "Reset Content";
		this._HTTP_STATUS_CODES['206'] = "Partial Content";
		this._HTTP_STATUS_CODES['300'] = "Multiple Choices";
		this._HTTP_STATUS_CODES['301'] = "Moved Permanently";
		this._HTTP_STATUS_CODES['302'] = "Found";
		this._HTTP_STATUS_CODES['303'] = "See Other";
		this._HTTP_STATUS_CODES['304'] = "Not Modified";
		this._HTTP_STATUS_CODES['305'] = "Use Proxy";
		this._HTTP_STATUS_CODES['306'] = "(Unused)";
		this._HTTP_STATUS_CODES['307'] = "Temporary Redirect";
		this._HTTP_STATUS_CODES['400'] = "Bad Request";
		this._HTTP_STATUS_CODES['401'] = "Unauthorized";
		this._HTTP_STATUS_CODES['402'] = "Payment Required";
		this._HTTP_STATUS_CODES['403'] = "Forbidden";
		this._HTTP_STATUS_CODES['404'] = "Not Found";
		this._HTTP_STATUS_CODES['405'] = "Method Not Allowed";
		this._HTTP_STATUS_CODES['406'] = "Not Acceptable";
		this._HTTP_STATUS_CODES['407'] = "Proxy Authentication Required";
		this._HTTP_STATUS_CODES['408'] = "Request Timeout";
		this._HTTP_STATUS_CODES['409'] = "Conflict";
		this._HTTP_STATUS_CODES['410'] = "Gone";
		this._HTTP_STATUS_CODES['411'] = "Length Required";
		this._HTTP_STATUS_CODES['412'] = "Precondition Failed";
		this._HTTP_STATUS_CODES['413'] = "Request Entity Too Large";
		this._HTTP_STATUS_CODES['414'] = "Request-URI Too Long";
		this._HTTP_STATUS_CODES['415'] = "Unsupported Media Type";
		this._HTTP_STATUS_CODES['416'] = "Requested Range Not Satisfiable";
		this._HTTP_STATUS_CODES['417'] = "Expectation Failed";
		this._HTTP_STATUS_CODES['500'] = "Internal Server Error";
		this._HTTP_STATUS_CODES['501'] = "Not Implemented";
		this._HTTP_STATUS_CODES['502'] = "Bad Gateway";
		this._HTTP_STATUS_CODES['503'] = "Service Unavailable";
		this._HTTP_STATUS_CODES['504'] = "Gateway Timeout";
		this._HTTP_STATUS_CODES['505'] = "HTTP Version Not Supported";

		try {
			if (window.XMLHttpRequest) {
				this.RequestObject = new XMLHttpRequest();
			} else if (typeof ActiveXObject != "undefined") {
				for (this._MSXML_TYPE = 0; this._MSXML_TYPE < this._MSXML_OBJECT_TYPES.length; ++this._MSXML_TYPE) {
					try {
						this.RequestObject = new ActiveXObject(this._MSXML_OBJECT_TYPES[this._MSXML_TYPE]);
						break;
					}
					catch(e){}
				}
				this._MSXML_TYPE = -1;
			}
		} catch (e) {
			this.displayError("Unable to create XMLHttpRequest object");
		}
		return this.RequestObject;
	}
};
