/*

	Javascript-based, process-base JSON interoperability code.
	
	Author: Mantzoukas Alexander
	Company: Enorasis S.A.
	Version: 3.0.1.0
	Email: alexander.mantzoukas@enorasis.com

*/

var RemoteScriptManager = new Class();

RemoteScriptManager.Inherit(Process);

RemoteScriptManager.Declare(
	{
		ErrorManager: new ErrorClass(),
		Timeout: -1,
		Counter: 0,
		OnlineRequests: 0,
		MaxRequests: -1,
		
		Messages: new ArrayProperty(),
		
		Statistics:
		{
			Aborts: 0,
			Timeouts: 0,
			Errors: 0,
			Received: 0,
			NotReceived: 0,
			TotalTimeCost: 0,
			TotalReceivedTimeCost: 0,
			TotalRequests: 0
		},
		
		Constructor: function ( name, main )
		{
			this.CreateThread(
				function()
				{
					for(var i = 0; i < this.Process.Messages.length; ++i)
					{
						var msg = this.Process.Messages.get(i);
						if (msg.IsSent)
						{
							if ( (this.Process.Timeout > 0) &&
								( (this.Process.TicksHasRun - msg.clock) >= this.Process.Timeout ) )
							{
								this.Process.RaiseTimeout( msg.counter );
							}
						}
						else if (this.Process.MaxRequests < 0 || 
							(this.Process.OnlineRequests < this.Process.MaxRequests))
						{
							this.Process.SendManagment( msg );
						}
					}
				}
			);
		},
		
		Send: function( _url, _callback, onReceive, onTimeout, onAbort, onError )
		{
			++this.Counter;
			
			_url += "&" + Math.floor( Math.random() * 100000 ) + "=" +  Math.floor( Math.random() * 100000 ) +
				"&" + Math.floor( Math.random() * 100000 ) + "=" +  Math.floor( Math.random() * 100000 );
			
			if (_callback && _callback != 'undefined')
				_callback += "\nCPU.Processes[" + this.ProcessIndex + 
					"].ConfirmLoad(" + this.Counter + ");";
			else
				_callback = "\nCPU.Processes[" + this.ProcessIndex + 
					"].ConfirmLoad(" + this.Counter + ");";
			
			var msg = {
					IsSent: false,
					clock: this.TicksHasRun,
					url: _url,
					callback: _callback,
					counter: this.Counter,
					onreceive: onReceive,
					ontimeout: onTimeout,
					onabort: onAbort,
					onerror: onError
				};
			
			var ErrorHandler = new ErrorHandlerClass( 
					Reference(this.onScriptError, this), false, _url 
				);
			
			ErrorHandler.IndexNumber = this.Counter;
			
			this.ErrorManager.ErrorHandlers.add( ErrorHandler );
			
			this.Messages.add( msg );
		},
		
		SendManagment: function( msg )
		{
			var _url = msg.url;
			_url += "&callback=" + escape( msg.callback );
			_url += "&counter=" + msg.counter;
			
			msg.IsSent = true;
			++this.OnlineRequests;
			++this.Statistics.TotalRequests;
			// if (this.onLoading) this.onLoading( msg.counter );
			
			$import( _url, "__autogenerated__JSONScript__" + msg.counter );
		},
		
		RaiseTimeout: function( i )
		{
			var j = this.FindMessage(i);
			if (j == -1) return;
			
			this.Statistics.TotalTimeCost += (this.TicksHasRun - this.Messages.get(j).clock);
			++this.Statistics.Timeouts;
			++this.Statistics.NoReceived;
			this.Clear(i, "ontimeout");
		},
		
		ConfirmLoad: function( i )
		{
			var j = this.FindMessage(i);
			if (j == -1) return;
			
			this.Statistics.TotalTimeCost += (this.TicksHasRun - this.Messages.get(j).clock);
			this.Statistics.TotalReceivedTimeCost += (this.TicksHasRun - this.Messages.get(j).clock);
			++this.Statistics.Received;
			this.Clear(i, "onreceive");
		},
		
		Abort: function( i )
		{
			++this.Statistics.Aborts;
			++this.Statistics.NoReceived;
			this.Clear(i, "onabort");
		},
		
		Clear: function( i, eventToFire )
		{
			var j = this.FindMessage(i);
			if (j == -1) return;
			
			if (eventToFire)
			{
				var msg = this.Messages.get(j);
				if (msg[ eventToFire ])
					msg[ eventToFire ]( this, msg );
			}
			
			--this.OnlineRequests;
			
			var el = $element( "__autogenerated__JSONScript__" + i );
			el.parentNode.removeChild( el );
			
			this.ErrorManager.ErrorHandlers.removeIndex(j);
			this.Messages.removeIndex(j);
		},
		
		FindMessage: function( countNumber )
		{
			var j = -1;
			for(j = 0; j < this.Messages.length; ++j)
			{
				if (countNumber == this.Messages.get( j ).counter)
				break;
			}
			
			if (j < 0 || j >= this.Messages.length)
				return -1;
			
			return j;
		},
		
		onScriptError: function( msgText, url, line, errorHandler )
		{
			++this.Statistics.Errors;
			++this.Statistics.NoReceived;
			--this.OnlineRequests;
			
			var j = this.FindMessage( errorHandler.IndexNumber );
			var msg = this.Messages.get(j);
			if (msg.onerror)
				msg.onerror( this, msg, msgText, url, line, errorHandler );
			//else
			//	alert( "Message: " + msgText + "\nUrl: " + url + "\nLine: " + line );
			
			// this.Clear( j, "onerror");
			return false; // Does not handles errors
		}
	}
);

