/**
 * Két objektum/érték összehasonlítását végző függvény.
 * @param mixed Az első érték.
 * @param mixed A második érték.
 */
 function compare(oValue1,oValue2) {
 	return ( ( oValue1 < oValue2 ) ? -1 : ( ( oValue1 > oValue2 ) ? 1 : 0 ) );
 }
 /**
  * A prioritásos sor prototípus beállításai.
  */
var CPriorityQueue = new Class ({
	/**
	 * Konstruktor függvény.
	 * @param fnCompare Az összehasonlítást végző függvény.
	 */
	 initialize : function (fnCompare) {
	 	this._queue = new Array();
	 	if ( typeof fnCompare == "function" ) {
	 		this._compare = fnCompare;
	 	}
 	},
 	_compare : function (oValue1,oValue2) {
 		return oValue1 - oValue2;
 	},
 	/**
 	 * A sor első elemét adja vissza.
 	 * @return Transport az első transzport elem.
 	 */
 	get : function () {
 		return ( this._queue.length ? this._queue.shift() : null );
 	},
 	
 	item : function (index) {
 		return this._queue[index];
 	},
 	/**
 	 * 
 	 */
 	peek : function () {
 		return ( this._queue.length ? this._queue[0] : null );
 	},
  	/**
  	 * 
  	 */
 	prioritize : function () {
 		this._queue.sort(this._compare);
 	},
 	
 	put : function (oValue) {
 		this._queue.push ( oValue );
 		this.prioritize ();
 	},
 	
 	remove : function (oValue) {
 		for (var i = 0 ; i < this._queue.length ; i++ ) {
 			if( this._queue[i] === oValue ) {
 				this._queue.splice (i,1);
 				return true;
 			}
 		}
 		return false;
 	},
 	
 	size : function () {
 		return this._queue.length;
 	}
 });
 
/**
 * Az Ajax kéréseket gyártó, kezelő objektum.
 *
 */
var CmooRequestManager = new Class({
		// a kérés max érvényességi ideje
		AGE_LIMIT : 60000,
		// A default prioritási érték amelyet egy XMLHtttp kérés felvesz a várakozási sorban. (1 a legmagasabb, 10 a legalacsonyabb) 
		DEFAULT_PRIORITY : 10,
		// A kérések státuszának ellenőrzési intervalluma microsecundumban.
		INTERVAL : 250,
		// Maximálisan ennyi XMLHttp kérés lehet aktív ( HTTP szabvány ).
		MAX_ACTIVE_REQUEST : 2,
		// Az aktív XMLHttp kérések.
		_active : new Array (),
		// Az XMLHttp kérések várakozási sora.
		_pending : new CPriorityQueue ( function ( oRequest1 , oRequest2 ) {
			return oRequest1.priority - oRequest2.priority;
		}),
		
		initialize : function () {
	 		this.scheduller.periodical(this.INTERVAL,this);
 		},
		/**
		 * Időalapú előre léptetés.
		 */
		_agePromote : function () {
			for (var i = 0; i < this._pending.size(); i++) {
				var oRequest = this._pending.item(i);
				if ( (oRequest.age += this.INTERVAL) >= this.AGE_LIMIT ){
					oRequest.age = 0;
					--oRequest.priority;
				}
			}
			this._pending.prioritize();
 		},
				
		_checkActiveRequests : function () {
			var oRequest = null;
			var oTransport = null;
			
			for ( var i = this._active.length-1; i >= 0; i-- ) {
				oRequest = this._active[i];
				oTransport = oRequest.transport;
				/*if (oTransport && oTransport.xhr.readyState == 4) {
					oRequest.active = false;
					this._active.splice(i,1);
					/*
					var fnCallback = null;
					if ( oTransport.status >= 200 && oTransport.status < 300 ) {
						if ( typeof oRequest.onSuccess == "function" ) {
							fnCallback = oRequest.onSuccess;
						}
					}
					else if ( oTransport.status == 304 ) {
						if ( typeof oRequest.onNotModified == "function" ) {
							fnCallback = oRequest.onNotModified;
						}
					}
					else {
						if ( typeof oRequest.onFailure == "function" ) {
							fnCallback = oRequest.onFailure;
						}
					}
						
					if 	( fnCallback != null ) {
						window.setTimeout((function (fnCallback, oRequest, oTransport) {
							return function () {
								fnCallback.call (oRequest.scope || window, {
									status : oTransport.status,
									data : oTransport.responseText,
									request : oRequest
								});
							}
						})(fnCallback, oRequest, oTransport),1);
					}
				}*/
				if (oTransport && oTransport.xhr.readyState == 4) {
					oRequest.active = false;
					oRequest.transport = null;
					this._active.splice(i,1);
					var fnCallback = null;
				}
			}
		},
		// Az XMLHttp objektumokat gyártó metódus.
		_createTransport : function (oRequest) {
			switch (oRequest.type ? oRequest.type.toUpperCase() : null) {
				case 'HTML': 
					return new Request.HTML (oRequest);
					break;
				case 'JSON':
					return new Request.JSON (oRequest);
					break;
				default : 
					return new Request (oRequest);
					break;	
			}
		},
		/**
		 * Elküldi a soronkövetkező XMLHttp kérést, amennyiben nincs függőben túl sok kérés. 
		 */
		_sendNext : function () {
			if ( this._active.length < this.MAX_ACTIVE_REQUEST) {
				var oRequest = this._pending.get();
				if( oRequest != null ) {
					this._active.push ( oRequest );
					oRequest.transport = this._createTransport (oRequest);
					oRequest.active = true;
					oRequest.transport.send();
				}
			}
		},
		/**
		 * Adott kérés visszavonása.
		 */
		cancel : function ( oRequest ) {
			// debug 
			//debug ('RM cancel request:'+oRequest);
			if (!$chk(oRequest)) {
				return;
			}
			// ha már az aktív kérések között van
			if ( !this._pending.remove (oRequest) ) {
				// a kérés abortálása
				// debug
				//debug ('a request nem várakkozik')
				if ($chk(oRequest) && $chk(oRequest.transport) &&  $type(oRequest.transport) == 'object') {
					oRequest.transport.cancel();
					// debug 
					//debug ('transport cancel');
				}
				var oReq = null;
				// első, vagy második kérés ? Eszerint eltávolítás.
				if ( this._active[0] === oRequest ) {
					oReq = this._active.shift();
				}
				else if ( this._active[1] === oRequest ) {
					oReq = this._active.pop();
				}
				if ($chk(oReq) && $chk(oReq.transport) &&  $type(oRequest.transport) == 'object') {
					//alert (oReq);
					try {
						oReq.transport.cancel();
					}	
					catch (ex) {
						window.alert (ex);
					}
					// debug 
					//debug ('transport cancel');
				}
				// ha van cancel eseménykezelő
				/*
				if ( typeof oRequest.onCancel == "function" ) {
					oRequest.onCancel.call ( oRequest.scope || window, { request : oRequest } );
				}*/
			}
		},
		getQueue : function () {
			return this._pending._queue;
		},
		/**
		 * Periódikus frissítés metódusa.
		 * @param oRequest 		 
		 */
		poll : function (oRequest) {
			oRequest.priority = 3;
			this.send (oRequest);
		},
		
		/**
		 * Prediktív lehívás, illetve többfázisú lekérdezés.
		 */
		prefetch : function (oRequest) {
			oRequest.priority = 5;
			this.send (oRequest);
		},
		  
		// A várakozási sorba helyez egy XMLHttp kérést.
		send : function ( oRequest ) {
			if ( typeof oRequest.priority != "number" ) {
				oRequest.priority = this.DEFAULT_PRIORITY;
			}
			oRequest.active = false;
			this._pending.put ( oRequest );
		},
		/**
		 * Felhsaználói műveletek. ( azonnal elküldi ).
		 */
		submit : function (oRequest) {
			// debug
			//debug ('RM submit:'+oRequest);
			oRequest.priority = 0;
			this.send (oRequest);
		},
		/**
		 * felküldés korlátozás.
		 */
		submitPart : function (oRequest) {
			oRequest.priority = 2;
			this.send (oRequest);
		},
		scheduller : function () {
			this._checkActiveRequests();
			this._sendNext ();
			this._agePromote ();
		}
	// a menedzser objektum kész, visszadjuk.

});

