/**
 * NM_RequestDispatcher.js
 *
 * bundle of classes and objects for request dispatching
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */

/**
 * Request event helper class for easyier handling of dispatch requests
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */
var NM_RequestDispatchEvent = new Class( {

	/**
	 * NM_RequestDispatchRequest object
	 *
	 * @access 	protected
	 * @var		objDispatchRequestuest
	 */
	objDispatchRequestuest: {},

	/**
	 * Initialize
	 *
	 * @access 	public
	 * @param	NM_RequestDispatchRequest objDispatchRequestuest
	 * @return	void
	 */
	initialize: function( objDispatchRequestuest )
	{
		if( $type( objDispatchRequestuest ) == 'object'
				&& true == objDispatchRequestuest.isType( 'NM_RequestDispatchRequest' )
				)
		{
			this.objDispatchRequestuest = objDispatchRequestuest;
			//console.dir( 'NM_RequestDispatchEvent: '+this.objDispatchRequestuest );
		}
		else
		{
			console.dir( 'NM_RequestDispatchEvent: '+$type( objDispatchRequestuest ) );
		}
	},

	/**
	 * Fire dispatcher request
	 *
	 * @access 	public
	 * @param	js object objParam
	 * @return	void
	 */
	fire: function( objParam )
	{
		NM_RequestDispatcher.fire( this.objDispatchRequestuest, objParam );
	}

} );


/**
 * main request dispatching object
 * handle the requests and the responses of the registered requests
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */
var NM_RequestDispatcher = {

	/**
	 * hash list of NM_ComponentRequestDispatch objects
	 *
	 * @access 	protected
	 * @var 	object objRequestList
	 */
	objRequestList: {},

	/**
	 * hash list of NM_RequestDispatchRequest objects
	 *
	 * @access 	protected
	 * @var 	object objDRList
	 */
	objDRList: new Hash(),

	/**
	 * register component requests for an event
	 *
	 * @access	public
	 * @param 	object objComRequest (NM_ComponentRequestDispatch)
	 * @return 	void
	 */
	register: function( objComRequest )
	{
		//NM_Console.dir( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'register: objComRequest' ), objComRequest );

		//check if the dispatching request event is already defined
		if( true == $defined( this.objRequestList[ objComRequest.getEvent() ] ) )
		{
			this.objRequestList[ objComRequest.getEvent() ][ this.objRequestList[ objComRequest.getEvent() ].length ] = objComRequest.toJson();
		}
		else
		{
			this.objRequestList[ objComRequest.getEvent() ] = [ objComRequest.toJson() ];
		}
	},

	/**
	 * fire all request objects for a dispatching event
	 *
	 * @access	public
	 * @param 	object objDispatchRequest (NM_RequestDispatchRequest)
	 * @return 	void
	 */
	fire: function( objDispatchRequest, objParam )
	{
		NM_Console.time( new NM_ConsoleMsg( 'ContentDispatcher', 'execution time' ) );

		//dispatching request is active
		objDispatchRequest.setOnFire();

		/**
		 * set dispatcher params
		 */
		if( true == $defined( objParam ) )
		{
			objDispatchRequest.getDispatcher().setParam( objParam );
		}

		//
		this._registerDR( objDispatchRequest );

		//get the list of request objects
		if( true == $defined( this.objRequestList[ objDispatchRequest.getEvent() ] ) )
		{
			var arrRequestList = this.objRequestList[ objDispatchRequest.getEvent() ];
		}
		else
		{
			var arrRequestList = []
		}

		//request list available
		if( arrRequestList.length > 0 )
		{
			NM_Console.group( new NM_ConsoleMsg( 'ContentDispatcher', 'fire event: '+objDispatchRequest.getEvent()+' (registered calls: '+ arrRequestList.length+')' ) );

			//set the com request list to the dispatching request
			objDispatchRequest.setRequestList( arrRequestList );

			//NM_Console.dir( new NM_ConsoleMsg( '->', 'dispatch request object ' ), objDispatchRequest.toJson() );

			//send Json request
			var JsonRequest = new Json.Remote( objDispatchRequest.getDispatcher().getUrl(), {

				//on request > dispatchWait
				onRequest: function() {
					this.dispatchWait( objDispatchRequest, true );
				}.bind( this ),

				//on state change > nothing
				onStateChange: function() {
					NM_Console.info( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'fire: onStateChange' ) );
				}.bind( this ),

				//on compplete > dispatchComplete
				onComplete: function( objResponse ) {
					this.dispatchComplete( objResponse );
				}.bind( this ),

				//on success > dispatchWait, dispatchSuccess
				onSuccess: function() {
					this.dispatchWait( objDispatchRequest, false );
					this.dispatchSuccess( objDispatchRequest );
				}.bind( this ),

				//on failure > nothing
				onFailure: function() {
					NM_Console.info( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'fire: onFailure' ) );
				}.bind( this )

			} ).send( objDispatchRequest.toJson() );

		}
		else
		{
			NM_Console.info( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'fire: no requests found' ) );
		}

	},

	/**
	 * dispatch the responses if the request status is complete
	 *
	 * @access	protected
	 * @param 	object objResponseData (Json)
	 * @return 	void
	 */
	dispatchComplete: function( objResponseData )
	{
		if( true == DMC_System.isObject( objResponseData )
				&& true == $defined( objResponseData.disp_response )
					)
		{
			//NM_Console.dir( new NM_ConsoleMsg( 'NM_RequestDispatcher::dispatchComplete', 'objResponseData > instance' ), objResponseData );
			var objDispatchResponse = new NM_RequestDispatchResponse( objResponseData.disp_response );

			//NM_Console.dir( new NM_ConsoleMsg( 'NM_RequestDispatcher::dispatchComplete', 'NM_RequestDispatchResponse > instance' ), objDispatchResponse );

			if( false == objDispatchResponse.isError() )
			{

				if( false == objDispatchResponse.isException() )
			{
					var arrResponseList = objDispatchResponse.getResponseList();
					$each( arrResponseList, function( objComData, strComName ) {

					try
					{
						//NM_Console.dir( new NM_ConsoleMsg( 'NM_RequestDispatcher::dispatchComplete', strComName+'::objComData' ), objComData );
							var objComResponse 	= new NM_ComponentResponseDispatch( objComData.response );
							//NM_Console.dir( new NM_ConsoleMsg( 'NM_RequestDispatcher::dispatchComplete', strComName+'::objComRequest' ), objComRequest );
							var objComRequest 	= new NM_ComponentRequestDispatch();
							objComRequest.init( objComData.request );

							if( false == objComResponse.isError() )
							{
								eval( objComRequest.getCbObjectName()+'.cbRequestDispatchOnComplete( objComResponse )' );
							}
							else
							{
								eval( objComRequest.getCbObjectName()+'.cbRequestDispatchOnError( objComResponse )' );
							}
					}
					catch( e )
					{
							NM_Console.warning( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'fire(): > ' + objComResponse.getName() + ' : ' + e ) );
					};

				}.bind( this ) );

			}
			else
			{
					this.dispatchException( objDispatchResponse );
			}
			}
			else
			{
				this.dispatchError( objDispatchResponse );
			}


			if( true == this.objDRList.hasKey( objDispatchResponse.getEvent() ) )
			{
				this._deleteDR( objDispatchResponse.getEvent() );
			}

		}
		else
		{
			NM_Console.warning( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'fire(): > no valid response object' ) );
		}

		NM_Console.groupEnd();
		NM_Console.timeEnd( new NM_ConsoleMsg( 'NM_RequestDispatcher', 'execution time' ) );

		objResponseData = null;
	},

	/**
	 * dispatch the success status to the request caller
	 *
	 * @access	protected
	 * @param 	object objDispatchRequest (NM_RequestDispatchRequest)
	 * @return 	void
	 */
	dispatchSuccess: function( objDispatchRequest )
	{
		var objCaller = objDispatchRequest.getCaller();
		try
		{
			if( objCaller.getMethodOnSuccess() != '' )
			{
				eval( objCaller.getObject()+'.'+objCaller.getMethodOnSuccess()+'( "'+objDispatchRequest.getEvent()+'" )' );
			}
		}
		catch( e )
		{
			NM_Console.error( new NM_ConsoleMsg( 'ContentDispatcher', 'dispatchSuccess: > ' + objCaller.getName() + ' : ' + e ) );
		}
	},


	/**
	 * dispatch the wait status to the request caller
	 *
	 * @access	protected
	 * @param 	object objDispatchRequest (NM_RequestDispatchRequest)
	 * @param 	blnStart (true = start waiting phase, false = stop the waiting phase)
	 * @return 	void
	 */
	dispatchWait: function( objDispatchRequest, blnStart )
	{
		var objCaller = objDispatchRequest.getCaller();
		try
		{
			if( objCaller.getMethodOnWait() != '' )
			{
				eval( objCaller.getObject()+'.'+objCaller.getMethodOnWait()+'( "'+objDispatchRequest.getEvent()+'",'+blnStart+')' );
			}
		}
		catch( e )
		{
			NM_Console.error( new NM_ConsoleMsg( 'ContentDispatcher', 'dispatchWait: > ' + objCaller.getName() + ' : ' + e ) );
		}
	},

	/**
	 * dispatch an excecption to the request caller
	 *
	 * @access	protected
	 * @param 	object objDispatchResponse (NM_RequestDispatchResponse)
	 * @return 	void
	 */
	dispatchException: function( objDispatchResponse )
	{
		var objCaller = objDispatchResponse.getCaller();
		try
		{
			if( objCaller.getMethodOnException() != '' )
			{
				eval( objCaller.getObject()+'.'+objCaller.getMethodOnException()+'( "'+objDispatchResponse.getEvent()+'", '+Json.toString( objDispatchResponse.getException() )+' )' );
			}
		}
		catch( e )
		{
			NM_Console.error( new NM_ConsoleMsg( 'ContentDispatcher', 'dispatchException: > ' + objCaller.getName() + ' : ' + e ) );
		}
	},

	/**
	 * dispatch an error to the request caller
	 *
	 * @access	protected
	 * @param 	object objDispatchResponse (NM_RequestDispatchResponse)
	 * @return 	void
	 */
	dispatchError: function( objDispatchResponse )
	{
		var objCaller = objDispatchResponse.getCaller();
		try
		{
			if( objCaller.getMethodOnError() != '' )
			{
				eval( objCaller.getObject()+'.'+objCaller.getMethodOnError()+'( objDispatchResponse )' );
			}
		}
		catch( e )
		{
			NM_Console.error( new NM_ConsoleMsg( 'ContentDispatcher', 'dispatchError: > ' + objCaller.getName() + ' : ' + e ) );
		}
	},

	/**
	 * register dispatching request
	 *
	 * @access	protected
	 * @param 	object objDR (NM_RequestDispatchRequest)
	 * @return 	void
	 */
	_registerDR: function( objDR )
	{
		if( this.objDRList == null )
		{
			this.objDRList = new Hash();
		}

		this.objDRList.set( objDR.getEvent(), objDR );
	},

	/**
	 * delete a dispatching request
	 *
	 * @access	protected
	 * @param 	string strEvent (dispatching event)
	 * @return 	void
	 */
	_deleteDR: function( strEvent )
	{
		if( this.objDRList != null )
		{
			this.objDRList.remove( strEvent );
		}
	}

};//end NM_RequestDispatcher


/**
 * class for the backend dispatcher request
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */
var NM_RequestDispatchRequest = new Class( {

	event: 			'',
	caller: 		{},
	dispatcher: 	'',
	requestList:	[],
	status: 		0, //0=deactive, 1=acitve

	setEvent: function( strEvent )
	{
		this.event = strEvent;
	},

	getEvent: function()
	{
		return this.event;
	},

	setCaller: function( objCaller )
	{
		this.caller = objCaller;
	},

	getCaller: function()
	{
		return this.caller;
	},

	setDispatcher: function( objDispatcher )
	{
		this.dispatcher = objDispatcher;
	},

	getDispatcher: function()
	{
		return this.dispatcher;
	},

	setRequestList: function( arrList )
	{
		this.requestList = arrList;
	},

	setDeactive: function()
	{
		this.status = 0;
	},

	setOnFire: function()
	{
		this.status = 1;
	},

	isOnFire: function()
	{
		return this.status;
	},

	toJson: function()
	{
		return {
			event:		this.event,
			caller:		this.caller.toJson(),
			dispatcher: this.dispatcher.toJson(),
			requestList:this.requestList,
			status:		this.status
		};
	},

	isType: function( strClass )
	{
		return 'NM_RequestDispatchRequest' == strClass;
	}

} );

/**
 * class for the backend dispatcher response
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */
var NM_RequestDispatchResponse = new Class( {

	caller: 		{},
	responseList: 	{},
	event: 			'', //dispatching event
	exception: 		{},
	error: 			{},

	initialize: function( objData )
	{
		//NM_Console.dir( new NM_ConsoleMsg( 'NM_RequestDispatchResponse::initialize', 'objData: ' ), objData );

		this.caller			= new NM_RequestDispatchCaller();
		this.caller.init( objData.caller );
		this.responseList	= objData.response_list;
		this.event 			= objData.event;
		this.exception		= objData.exception;
		this.error			= objData.error;
	},

	getResponseList: function()
	{
		return this.responseList;
	},

	getCaller: function()
	{
		return this.caller;
	},

	getEvent: function()
	{
		return this.event;
	},

	isException: function()
	{
		return ( $type( this.exception ) == 'object'  );
	},

	getException: function()
	{
		return this.exception;
	},

	isError: function()
	{
		return ( $type( this.error ) == 'object'  );
	},

	getError: function()
	{
		return this.error;
	}


} );


/**
 * class for the dispatching caller
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */
var NM_RequestDispatchCaller = new Class( {

	name: 	'',		//caller component name
	object: '',		//callback js object
	method: {		//callback methods
		success:	'', //will be called, if the dispatching was successed
		wait: 		'', //will be called, while the dispatching is running
		error: 		'', //will be called, if the dispatching was not successed
		exception:	''	//will be called, if a defined exception event is habeppend in the backend
	},

	setName: function( strName )
	{
		this.name = strName;
	},

	getName: function()
	{
		return this.name;
	},

	setObject: function( strObjName )
	{
		this.object = strObjName;
	},

	getObject: function()
	{
		return this.object;
	},

	setMethodOnSuccess: function( strMethod )
	{
		this.method.success = strMethod;
	},

	getMethodOnSuccess: function()
	{
		return this.method.success;
	},

	setMethodOnWait: function( strMethod )
	{
		this.method.wait = strMethod;
	},

	getMethodOnWait: function()
	{
		return this.method.wait;
	},

	setMethodOnError: function( strMethod )
	{
		this.method.error = strMethod;
	},

	getMethodOnError: function()
	{
		return this.method.error;
	},

	setMethodOnException: function( strMethod )
	{
		this.method.exception = strMethod;
	},

	getMethodOnException: function()
	{
		return this.method.exception;
	},

	toJson: function()
	{
		return {
			name: 		this.getName(),
			object: 	this.getObject(),
			method: 	this.method
		};
	},

	init: function( objData )
	{
		if( $type( objData ) == 'object'  )
		{
			this.name		= objData.name;
			this.object		= objData.object;
			this.method 	= objData.method;
		}
	}

} );


/**
 * class for the backend dispatcher
 *
 * @author	Steffen Heinzelmann <shi@dmc.de>
 * @version	$Id: NM_RequestDispatcher.js 84734 2011-09-13 08:46:14Z sheinzelmann $
 */
var NM_RequestDispatchDispatcher = new Class( {

	url:		'',
	dispatcher: '',
	method: 	'',
	param:		{},

	setUrl: function( strUrl )
	{
		this.url = strUrl;
	},

	getUrl: function()
	{
		return this.url;
	},

	setDispatcher: function( strDispatcher )
	{
		this.dispatcher = strDispatcher;
	},

	setMethod: function( strMethod )
	{
		this.method = strMethod;
	},

	setParam: function( objParam )
	{
		this.param = objParam;
	},

	toJson: function()
	{
		return {
			url:		this.url,
			dispatcher: this.dispatcher,
			method: 	this.method,
			param:		this.param
		};
	}

} );
