/*!
	State Model Sample Code -- Queue Manager
	--------------------------------------------
	Copyright 2009 Kevin Dolan
	-http://www.thekevindolan.com
	
	Code licensed under the MIT license
	-See license.txt
	
	v0.1
*/

var queues = new Array();

/*! public, accessible
	queueManager constructor
	Params:
		-call : url of file to send requests to
		-dataManager : the dataManager object whose state will be updated by this
		-[pollTimeout] : time between polls of the server
			-integer : time in milliseconds or
			-false (default) : no polling
*/
function queueManager(call, dataManager, pollTimeout) {
	this.call = call;
	this.pollTimeout = timeout;
	this.number = 0;
	this.queue = new Array();
	this.active = new Array();
	this.busy = false;
	this.id = queues.length;
	this.dataManager = dataManager;
	var d = new Date();
	this.lastUpdate = d.getTime();
	queues[queues.length] = this;
	
	//Initialize the server communication object depending on browser
	this.ajax;
	// Firefox, Opera 8.0+, Safari
	try{ this.ajax = new XMLHttpRequest(); }
	catch (e) {
		// Internet Explorer
		try { this.ajax = new ActiveXObject("Msxml2.XMLHTTP"); }
		catch (e) {
			try { this.ajax = new ActiveXObject("Microsoft.XMLHTTP"); }
			catch (e) { alert("Your browser does not support AJAX!"); }
		}
	}
	
	//TODO - consider whether or not this code is right...
	this.ajax.onreadystatechange = function() {
        if(this.ajax.readyState==4)
			this.processResponse(this.responseText);
	};
	
	/*! public, accessible
		add an request to the queue
		Params:
			-request : a reference to the action or navigation object
			-params : the parameters to be sent with the request
			-[nonImmediate] : whether or not this object can wait for the next poll
				-false (default) : this request will be performed as soon as the AJAX is not busy
				-true : this request will wait until the next poll to be sent
	*/
	this.addRequest = function (request, params, nonImmediate) {
		this.addToQueue(request, params, nonImmediate);
		if(nonImmediate && !this.busy)
			this.sendRequest();
	};
	
	/*! private
		Add an item to the back of the queue
	*/
	this.addToQueue = function(request, params, nonImmediate) {
		this.queue[this.queue.length] = {request: request, params: params, nonImmediate: nonImmediate};
	};
	
	/*! private
		Return true if there are any priority items in the queue
	*/	
	this.hasPriority = function() {
		for(var i in this.queue)
			if(!this.queue[i].nonImmediate)
				return true;
		return false;
	};
		
	/*! private
		Handle a response from the server
	*/
	this.processResponse = function(responseText) {
		//parse the response string
		response = JSON.parse(responseText);
		
		//create the empty errors array
		errors = new Array();
		for(var i in this.active)
			errors[i] = false;
		
		//for each of the items in the response array
		//	decide if it is an error, or a data update
		for(var i in response) {
			responseItem = response[i];
			if(responseItem.error)
				errors[responseItem.id] = responseItem;
			else
				this.handleDataResponse(responseItem);
		}
		
		//notify all the requests of success/failure
		for(var i in errors) {
			current = this.active[i];
			if(errors[i])
				current.request.onError( current.params, errors[i] );
			else
				current.request.onSuccess( current.params );
		}
		
		//update the queue's state
		this.active = new Array();
		this.busy = false;
		var d = new Date();
		this.lastUpdate = d.getTime();
		if(this.hasPriority())
			this.sendRequest();
		else
			this.delayPoll();
	};
	
	/*! private
		Notify the data manager of a data update
	*/
	this.handleDataResponse = function(response) {
		//TODO - Implement me
	};
	
	/*! private
		Send all requests in the queue to the server or
		if the queue is empty, simply request a poll
	*/
	this.sendRequest = function() {
		this.busy = true;
		this.active = this.queue;
		this.queue = new Array();
		
		request = {lastupdate: this.lastUpdate, requests: this.active};
		
		//Format the request array as a JSON string
		requestText = JSON.stringify(request);
		
		//Send the AJAX request
		this.ajax.open("POST",this.call,true);
	    param = "requests=" + requestText;
        this.ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        this.ajax.setRequestHeader("Content-length", param.length);
        this.ajax.setRequestHeader("Connection", "close");
		this.ajax.send(param);
	};
	
	/*! private
		If polling is enabled, set the timeout for the poll
	*/
	this.delayPoll = function() {
		if(this.pollTimeout)
			setTimeout("queues["+this.id+"].poll()", this.pollTimeout);
	};
	
	/*! private
		If the AJAX is not busy, send request
	*/
	this.poll = function {
		if(!this.busy)
			this.sendRequest();
	};
	
	//Start the first poll timeout
	this.delayPoll();
	return true;
};
