//==============================================================================
// HTTPRequest Class
// Notes:
//	o Based on the common XMLHttpRequest object
//		o See: http://en.wikipedia.org/wiki/XMLHTTPRequest
//------------------------------------------------------------------------------
//==============================================================================
// Class Contants
//==============================================================================
//------------------------------------------------------------------------------
// XMLHTTPRequest readyState constants
var XMLHTTPREQUEST_READYSTATE_UNINIT		= 0;
var XMLHTTPREQUEST_READYSTATE_OPEN		= 1;
var XMLHTTPREQUEST_READYSTATE_SENT		= 2;
var XMLHTTPREQUEST_READYSTATE_RECEIVING		= 3;
var XMLHTTPREQUEST_READYSTATE_LOADED		= 4;

// Common HTTP protocol statuses
var HTTPREQUEST_HTTP_STATUS_OK			= 200;
var HTTPREQUEST_HTTP_STATUS_FORBIDDEN		= 403;
var HTTPREQUEST_HTTP_STATUS_MISSING		= 404;
var HTTPREQUEST_HTTP_STATUS_INTERNALERROR	= 500;
//------------------------------------------------------------------------------
//==============================================================================
// Constructor
//==============================================================================
//------------------------------------------------------------------------------
function HTTPRequest( method, url, async, username, password ) {
	//---
	// Initialize
	this._initialize(method, url, async, username, password);
	//---
}
//==============================================================================
// Public Methods
//==============================================================================
//------------------------------------------------------------------------------
function HTTPRequest__abort() {
	this._initialize();
}
//------------------------------------------------------------------------------
function HTTPRequest__getAllResponseHeaders() {
	return this.getXMLHTTPRequest().getAllResponseHeaders();
}
//------------------------------------------------------------------------------
function HTTPRequest__getResponseHeader( headerName ) {
	return this.getXMLHTTPRequest().getResponseHeader(headerName);
}
//------------------------------------------------------------------------------
function HTTPRequest__open( method, url, async, username, password ) {
	//---
	// Override any setup with the given arguments
	this._override(method, url, async, username, password);

	// Set any request headers as needed
	for ( var i=0; i < this._requestHeaders.length; i++ ) {
		this.getXMLHTTPRequest().setRequestHeader(this._requestHeaders[i].label, this._requestHeaders[i].value);
	}

	// Open
	this.getXMLHTTPRequest().open(this.getMethod(), this.getURL(), this.getAsync(), this.getUsername(), this.getPassword());
	//---
}
//------------------------------------------------------------------------------
function HTTPRequest__send( postData ) {
	//---
	// Default postData to an empty string
	if ( ! postData ) {
		postData="";
	}

	// If POST method, automatically include required HTTP headers
	// according to the protocol if they're not already set
	if ( this.getMethod().toUpperCase() == "POST" ) {
		if ( ! this.getRequestHeader('Content-Type') ) {
			this.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		}
		if ( ! this.getRequestHeader('Content-Length') ) {
			this.setRequestHeader('Content-Length', postData.length);
		}
		if ( ! this.getRequestHeader('Connection') ) {
			this.setRequestHeader('Connection', 'close');
		}
	}

	// Send
	this.getXMLHTTPRequest().send(postData);

	// If async is true, return null, otherwise process and return the response
	if ( this.getAsync() ) {
		return null;
	} else {
		return ( this._processRequest() ) ? true : false;
	}
	//---
}
//------------------------------------------------------------------------------
function HTTPRequest__getRequestHeader( label ) {
	//---
	for ( var i=0; i < this._requestHeaders.length; i++ ) {
		if ( label == this._requestHeaders[i].label ) {
			return this._requestHeaders[i].value;
		}
	}
	//---
	return null;
}
//------------------------------------------------------------------------------
function HTTPRequest__setRequestHeader( label, value ) {
	var found=0;
	//---
	// Quote label for use in regex
	var safeLabel = label.replace(/([^A-Za-z0-9])/g , "\\$1");

	// Look for existing header to update
	for ( var i=0; i < this._requestHeaders.length; i++ ) {
		if ( this._requestHeaders[i].label.match(new RegExp(safeLabel, "i")) ) {
			this._requestHeaders[i].label = label;
			this._requestHeaders[i].value = value;
			found=1;
		}
	}

	// If header wasn't already found, let's just add it
	if ( ! found ) {
		this.addRequestHeader(label, value);
	}
}
//------------------------------------------------------------------------------
function HTTPRequest__addRequestHeader( label, value ) {
	this._requestHeaders.push( { 'label': label, 'value': value } );
}
//------------------------------------------------------------------------------
function HTTPRequest__removeRequestHeader( label ) {
	//---
	// Quote label for use in regex
	var safeLabel = label.replace(/([^A-Za-z0-9])/g , "\\$1");

	// Look for existing header to remove
	for ( var i=0; i < this._requestHeaders.length; i++ ) {
		if ( this._requestHeaders[i].label.match(new RegExp(safeLabel, "i")) ) {
			this._requestHeaders.splice(i, 1);
			break; // Stop looking
		}
	}
	//---
}
//------------------------------------------------------------------------------
//==============================================================================
// Private Methods
//==============================================================================
//------------------------------------------------------------------------------
function HTTPRequest___initialize( method, url, async, username, password ) {
	//---
	// Default data members
	this.setMethod( ( method ) ? method : 'get' );
	this.setURL( ( url ) ? url : '' );
	this.setAsync( ( async != null ) ? async : true );
	this.setUsername( ( username ) ? username : '' );
	this.setPassword( ( password ) ? password : '' );
	this.setRequestHeaders( new Array() );

	// Create XMLHTTPRequest
	this.setXMLHTTPRequest( this._newXMLHTTPRequest() );
	//---
}
//------------------------------------------------------------------------------
function HTTPRequest___override( method, url, async, username, password ) {
	//---
	// Default data members
	this.setMethod( ( method ) ? method : this.getMethod() );
	this.setURL( ( url ) ? url : this.getURL() );
	this.setAsync( ( async != null ) ? async : this.getAsync() );
	this.setUsername( ( username ) ? username : this.getUsername() );
	this.setPassword( ( password ) ? password : this.getPassword() );
	//---
}
//------------------------------------------------------------------------------
function  HTTPRequest___newXMLHTTPRequest() {
	//---
	// This is the only place that can refer to XMlHttpRequest with
	// improper camel-case.
	if ( XMLHttpRequest ) {
		return new XMLHttpRequest();
	} else if ( ActiveXObject ) {
		return new ActiveXObject('Microsoft.XMLHTTP');
	} else {
		alert("We're sorry, but you need a newer browser to view our website.");
	}
	//---
}
//------------------------------------------------------------------------------
function HTTPRequest___processResponse() {
	//---
	// Wait until response is loaded
	if ( this.getXMLHTTPRequest().readyState == XMLHTTPREQUEST_READYSTATE_LOADED ) {

		// Check HTTP status. We try{} this to avoid "uncaught"
		// exceptions in firefox while checking http.status.
		var httpStatus = 0;
		try {
			httpStatus = http.status;
		} catch ( e ) {
			// Nothing
		}

		// If OK status, return success
		return ( httpStatus == HTTPREQUEST_HTTP_STATUS_OK ) ? true : false;
	}
	//---
}
//------------------------------------------------------------------------------
//==============================================================================
// Getters
//==============================================================================
//------------------------------------------------------------------------------
function HTTPRequest__getMethod() {
	return this._method;
}
//------------------------------------------------------------------------------
function HTTPRequest__getURL() {
	return this._url;
}
//------------------------------------------------------------------------------
function HTTPRequest__getAsync() {
	return this._async;
}
//------------------------------------------------------------------------------
function HTTPRequest__getUsername() {
	return this._username;
}
//------------------------------------------------------------------------------
function HTTPRequest__getPassword() {
	return this._password;
}
//------------------------------------------------------------------------------
function HTTPRequest__getRequestHeaders() {
	return this._requestHeaders;
}
//------------------------------------------------------------------------------
function HTTPRequest__getXMLHTTPRequest() {
	return this._XMLHTTPRequest;
}
//------------------------------------------------------------------------------
function HTTPRequest__getOnreadystatechange() {
	return this._XMLHTTPRequest.onreadystatechange;
}
//------------------------------------------------------------------------------
function HTTPRequest__getReadyState() {
	return this._XMLHTTPRequest.readyState;
}
//------------------------------------------------------------------------------
function HTTPRequest__getResponseText() {
	return this._XMLHTTPRequest.responseText;
}
//------------------------------------------------------------------------------
function HTTPRequest__getResponseXML() {
	return this._XMLHTTPRequest.responseXML;
}
//------------------------------------------------------------------------------
function HTTPRequest__getStatus() {
	return this._XMLHTTPRequest.status;
}
//------------------------------------------------------------------------------
function HTTPRequest__getStatusText() {
	return this._XMLHTTPRequest.statusText;
}
//------------------------------------------------------------------------------
//==============================================================================
// Setters
//==============================================================================
//------------------------------------------------------------------------------
function HTTPRequest__setMethod( set )  {
	this._method = set.toLowerCase();
}
//------------------------------------------------------------------------------
function HTTPRequest__setURL( set )  {
	this._url = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setAsync( set )  {
	this._async = ( set ) ? true : false;
}
//------------------------------------------------------------------------------
function HTTPRequest__setUsername( set )  {
	this._username = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setPassword( set )  {
	this._password = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setRequestHeaders( set )  {
	this._requestHeaders = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setXMLHTTPRequest( set )  {
	this._XMLHTTPRequest = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setOnreadystatechange( set )  {
	this._XMLHTTPRequest.onreadystatechange = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setReadyState( set )  {
	this._XMLHTTPRequest.readyState = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setResponseText( set )  {
	this._XMLHTTPRequest.responseText = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setResponseXML( set )  {
	this._XMLHTTPRequest.responseXML = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setStatus( set )  {
	this._XMLHTTPRequest.status = set;
}
//------------------------------------------------------------------------------
function HTTPRequest__setStatusText( set )  {
	this._XMLHTTPRequest.statusText = set;
}
//------------------------------------------------------------------------------
//==============================================================================
// Class Prototyping
//==============================================================================
//------------------------------------------------------------------------------
// Public Methods
HTTPRequest.prototype.abort			= HTTPRequest__abort;
HTTPRequest.prototype.getAllResponseHeaders	= HTTPRequest__getAllResponseHeaders;
HTTPRequest.prototype.getResponseHeader		= HTTPRequest__getResponseHeader;
HTTPRequest.prototype.open			= HTTPRequest__open;
HTTPRequest.prototype.send			= HTTPRequest__send;
HTTPRequest.prototype.getRequestHeader		= HTTPRequest__getRequestHeader;
HTTPRequest.prototype.setRequestHeader		= HTTPRequest__setRequestHeader;
HTTPRequest.prototype.addRequestHeader		= HTTPRequest__addRequestHeader;
HTTPRequest.prototype.removeRequestHeader	= HTTPRequest__removeRequestHeader;
// Private methods
HTTPRequest.prototype._initialize		= HTTPRequest___initialize;
HTTPRequest.prototype._override			= HTTPRequest___override;
HTTPRequest.prototype._newXMLHTTPRequest	= HTTPRequest___newXMLHTTPRequest;
HTTPRequest.prototype._processResponse		= HTTPRequest___processResponse;
// Getters
HTTPRequest.prototype.getMethod			= HTTPRequest__getMethod;
HTTPRequest.prototype.getURL			= HTTPRequest__getURL;
HTTPRequest.prototype.getAsync			= HTTPRequest__getAsync;
HTTPRequest.prototype.getUsername		= HTTPRequest__getUsername;
HTTPRequest.prototype.getPassword		= HTTPRequest__getPassword;
HTTPRequest.prototype.getRequestHeaders		= HTTPRequest__getRequestHeaders;
HTTPRequest.prototype.getXMLHTTPRequest		= HTTPRequest__getXMLHTTPRequest;
HTTPRequest.prototype.getOnreadystatechange	= HTTPRequest__getOnreadystatechange;
HTTPRequest.prototype.getReadyState		= HTTPRequest__getReadyState;
HTTPRequest.prototype.getResponseText		= HTTPRequest__getResponseText;
HTTPRequest.prototype.getResponseXML		= HTTPRequest__getResponseXML;
HTTPRequest.prototype.getStatus			= HTTPRequest__getStatus;
HTTPRequest.prototype.getStatusText		= HTTPRequest__getStatusText;
// Setters
HTTPRequest.prototype.setMethod			= HTTPRequest__setMethod;
HTTPRequest.prototype.setURL			= HTTPRequest__setURL;
HTTPRequest.prototype.setAsync			= HTTPRequest__setAsync;
HTTPRequest.prototype.setUsername		= HTTPRequest__setUsername;
HTTPRequest.prototype.setPassword		= HTTPRequest__setPassword;
HTTPRequest.prototype.setRequestHeaders		= HTTPRequest__setRequestHeaders;
HTTPRequest.prototype.setXMLHTTPRequest		= HTTPRequest__setXMLHTTPRequest;
HTTPRequest.prototype.setOnreadystatechange	= HTTPRequest__setOnreadystatechange;
HTTPRequest.prototype.setReadyState		= HTTPRequest__setReadyState;
HTTPRequest.prototype.setResponseText		= HTTPRequest__setResponseText;
HTTPRequest.prototype.setResponseXML		= HTTPRequest__setResponseXML;
HTTPRequest.prototype.setStatus			= HTTPRequest__setStatus;
HTTPRequest.prototype.setStatusText		= HTTPRequest__setStatusText;
//------------------------------------------------------------------------------

