/**
  *	This class is responsible for AJAX operations
  *
  *	@author Vytenis Urbonavicius <vytenis.urbonavicius@myhost.lt>
  *	@version 0.0
  */
function comancheAjax( httpAddress ) {
	
	function idle() {
		// Do nothing
	}
	
	/**
	  *	This parameter stores timeout in seconds
	  * Use -1 to disable timeout (or do not set it at all)
	  * Use 0 to trigger timeout event if response is not instant (not recommended)
	  * Use any positive number to set timeout in seconds
	  *
	  *	@author Vytenis Urbonavicius <vytenis.urbonavicius@myhost.lt>
	  *	
	  *	@var timeout
	  */
	this.timeout = -1;
	
	// Events
	
	this.onAjaxNotInitialized = idle;
	this.onAjaxRequestSetUp = idle;
	this.onAjaxRequestSent = idle;
	this.onAjaxRequestInProcess = idle;
	this.onAjaxRequestComplete = idle;
	this.onAjaxTimeout = idle;
	
	// Framefork variables
	
	this.time_left = this.timeout + 1;
	this.continue_ticking = false;
	this.request_number = 0;
	
	this.httpAddress = httpAddress;
	this.lastAjaxResponse = undefined;
	
	this.ajaxObject = undefined;
	
	this.stateChangedEventGenerator = function ( comancheAjaxObject, request_number ) {
		
		return function() {
			
			if ( comancheAjaxObject.ajaxObject.readyState == 0 ) {
				comancheAjaxObject.onAjaxNotInitialized();
			} else if ( comancheAjaxObject.ajaxObject.readyState == 1 ) {
				comancheAjaxObject.onAjaxRequestSetUp();
			} else if ( comancheAjaxObject.ajaxObject.readyState == 2 ) {
				comancheAjaxObject.onAjaxRequestSent();
			} else if ( comancheAjaxObject.ajaxObject.readyState == 3 ) {
				comancheAjaxObject.onAjaxRequestInProcess();
			} else if ( comancheAjaxObject.ajaxObject.readyState == 4 ) {
				if ( request_number == comancheAjaxObject.request_number ) {
					comancheAjaxObject.continue_ticking = false;
					comancheAjaxObject.lastAjaxResponse = comancheAjaxObject.ajaxObject.responseText;
					comancheAjaxObject.rebuildAjax();
					comancheAjaxObject.onAjaxRequestComplete();
				}
			}
			
		}
		
	};
	
	this.rebuildAjax = function() {
		
		this.request_number++;
		this.continue_ticking = false;
		this.time_left = this.timeout + 1;
		
		try {
			this.ajaxObject = new XMLHttpRequest();
		} catch( e ) {
			try {
				this.ajaxObject = new ActiveXObject( "Msxml2.XMLHTTP" );
			} catch( e ) {
				try {
					this.ajaxObject = new ActiveXObject( "Microsoft.XMLHTTP" );
				} catch( e ) {}
			}
		}
		
		if ( this.ajaxObject != undefined ) {
			this.ajaxObject.onreadystatechange = this.stateChangedEventGenerator( this, this.request_number );
		}
		
	};
	
	this.checkTimeout = function() {
		
		if ( this.continue_ticking && ( this.time_left != -1 ) ) {
			
			this.time_left--;
			
			if ( this.time_left == 0 ) {
				this.rebuildAjax();
				this.onAjaxTimeout();
			} else {
				var _self = this;
				setTimeout( function() { _self.checkTimeout(); }, 1000 );
			}
			
		}
		
	};
	
	/**
	  *	This function gathers last ajax response
	  *
	  *	@author Vytenis Urbonavicius <vytenis.urbonavicius@myhost.lt>
	  *	@version 0.0
	  *
	  *	@return string/false string last ajax response or undefined on error
	  */
	this.getResponse = function() {
		return this.lastAjaxResponse;
	};
	
	/**
	  *	This function sends an AJAX request
	  *
	  *	@author Vytenis Urbonavicius <vytenis.urbonavicius@myhost.lt>
	  *	@version 0.0
	  *
	  * @param string address of a file on web
	  * @param string method GET/POST (POST is recommended as GET format may vary in non standart URL modes)
	  * @param string parameters in GET style without leading question mark
	  *
	  *	@return bool true on success
	  */
	this.sendRequest = function ( address, method, arguments ) {
		
		this.rebuildAjax();
		
		if ( this.ajaxObject.readyState != 0 ) {
			return false;
		}
		
		if ( ( method != "GET" ) && ( method != "POST" ) ) {
			return false;
		}
		
		if ( method == "GET" ) {
			address += '?' + arguments;
		}
		
		this.ajaxObject.open( method, this.httpAddress + '/' + address, true );
		
		if ( method == "GET" ) {
			this.ajaxObject.send( null );
		} else {
			this.ajaxObject.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" );
			this.ajaxObject.setRequestHeader( "Content-length", arguments.length );
			this.ajaxObject.setRequestHeader( "Connection", "close" );
			this.ajaxObject.send( arguments );
		}
		
		this.continue_ticking = true;
		this.checkTimeout();
		
		return true;
		
	};
	
}
