/*
Class: ItemRequest
	
	
Note:
	The ItemRequest requires an XHTML doctype.

Arguments:


Options:

	
Events:
	onComplete - a function to fire when you're done retrieving data.
*/
var ItemRequest = new Class({
	
	options: {
//		onComplete: Class.empty,
	//	onError: Class.empty,
		//listItemManager : null
		elementsPerPage : 0,
		elementThreshHold : 4,
		totalElements: 0
	},
	
	initialize : function( options ) {
		this.setOptions( options );
		this.currentRequestItem = -1;
		//this.requestQ = [];
		this.currentDataRetrieval = null;
		this.requestQ = new PriorityQueue({});
	},
	
	
	// this method will 
	retrieveItem : function (elementNumber, itemPriority ) {
		
		// determine if we need to load this data..
		var elementsCount = parseInt(elementNumber * this.options.elementsPerPage);
		if (LoadedItemManager.isLoaded(elementNumber))
		{
			this.fireEvent('onComplete',{'itemNumber':elementNumber,'response': ''});
		}
		else
		{
			this.addRequestItem(elementNumber, itemPriority);
			if ( this.currentDataRetrieval == null )
			{
			    this.createDataRetrieval(this.requestQ.peek());
			}
		}
	},
	
	addRequestItem: function (itemNumber, itemPriority) {
		var elementsCount = parseInt(itemNumber * this.options.elementsPerPage);
		if (! LoadedItemManager.isLoaded(itemNumber)  && (itemNumber >= 0) && (elementsCount <= this.options.totalElements))	{
			this.requestQ.add(itemNumber, itemPriority);
			if ( this.currentDataRetrieval == null )
			{
			    this.createDataRetrieval(this.requestQ.peek());
			}	
		}
	},
	
	
	// this is the callback method for the oncomplete event from the dataretreiver
	// this method will call the oncomplete event to notify interested parties.
	dataRetrievalComplete : function(response) {
		LoadedItemManager.loadItem(this.currentRequestItem);
		// fire the onComplete event
		var itemNumberRetrieved = this.clearDataRetrieval();
		this.fireEvent('onComplete', {'itemNumber':itemNumberRetrieved,'response': response});
		// if we have more items to load then do it now.
		if (this.requestQ.length() > 0)
		{
			this.createDataRetrieval(this.requestQ.peek());
			this.currentDataRetrieval.retrieveData(this.currentRequestItem);
		}
	},
	
	//this method will handle error processing that will be needed.
	dataRetrievalError : function(response) {
		//remove the last request.
		var itemNumberRetrieved = this.clearDataRetrieval();
		this.fireEvent('onError', {'itemNumber':itemNumberRetrieved,'response': response});
	},
	
	clearDataRetrieval : function() {
		// remove the last request from the queue and clear the request
		var lastItemNumber = this.currentRequestItem;
		this.requestQ.remove(lastItemNumber);
		this.currentDataRetrieval = null;
		return lastItemNumber;
	},
	
	
	// this mehtod will ceate a DataRetrieval object
	// then set up the events to the complete and error callback functions.
	createDataRetrieval : function( itemNumber ) {
		this.currentRequestItem = itemNumber;
		this.currentDataRetrieval = new DataRetrieval(itemNumber, {elementsPerPage : this.options.elementsPerPage});
		this.currentDataRetrieval.retrieveData();
		this.currentDataRetrieval.addEvent('onComplete',function(response) {this.dataRetrievalComplete(response);}.bind(this));
		this.currentDataRetrieval.addEvent('onError',function(response) {this.dataRetrievalError(response);}.bind(this));
	}	
	
	
});

ItemRequest.implement(new Options);
ItemRequest.implement(new Events);


var PriorityQueue = new Class({
	
	options: {
	
	},
	
	initialize: function(options){
		this.queue = [];
	},
	
	add: function(itemNumber, itemPriority){
		//if item is not in the queue, add it
		if(this.queue.length == 0 || !(this.contains(itemNumber))){
			var item = {
				number: itemNumber,
				priority: itemPriority
			};
			this.queue.push(item);
		} else {
			//else increase the priority of the item
			var item = this.remove(itemNumber);
			item.priority += itemPriority;
			this.queue.push(item);
		}
		this.sort();
		//console.log(this.queue);
	},
	
	sort: function(){
		if(this.queue.length > 1){
			this.queue.sort(function(a,b){ 
				return a.priority - b.priority; 
			});
		}
	},
	
	contains: function(itemNumber){
		var retValue = false;	
		if(this.findIndex(itemNumber) >= 0){
			retValue = true;
		}
		return retValue;
	},
	
	findIndex: function(itemNumber){
		var retValue = -1;
		this.queue.each(function(item, index){
			if(item.number == itemNumber){
				retValue = index;
			}
		});
		return retValue;
	},
	
	remove: function(itemNumber){
		var itemIndex = this.findIndex(itemNumber);
		var retValue = this.queue[itemIndex];
		this.queue.remove(retValue);
		//console.log(this.queue);
		return retValue;
	},
	
	pop: function(){
		//return the first item
		var itemNumber = this.queue[0];
		this.queue.remove(itemNumber);
		return itemNumber.number;
		//this.queue.shift();
	},
	
	// this function will return the first item in the Q
	// but it will not remove it from the queue
	peek: function(){
	    return this.queue[0].number;
	},
	
	length: function() {
	    return this.queue.length;
	}
});

PriorityQueue.implement(new Options);
PriorityQueue.implement(new Events);
