var NgbDebug = new function __NgbDebug()
{
	this.Print = function ( Message )
	{
		alert( Message );
	}
}

function NgbEVMDelegator( /*function*/ _fn )
{
	try
	{
		this.fn = _fn;
	}
	catch( e ) 
	{
		NgbDebug.Print ( 'EVMDelegator Error!' );
	}
}

function __NgbCommand( _Type, _Command, _ArgForCommand )
{
	this.Type = _Type;
	this.Command = _Command;
	this.nExecuteCount = 0;
	this.ArgForCommand = _ArgForCommand;
	this.IsExecute = false;
	
	this.Execute = function( arg )
	{
		if( !this.IsExecute )
		{
			this.IsExecute = true;
			this.nExecuteCount++;

			var argument = new Array();
			argument[ 0 ] = arg;
			argument[ 1 ] = this.ArgForCommand;

			this.Command.fn.apply( this.Command.fn, argument );
			this.IsExecute = false;
		}
		else
		{
			NgbDebug.Print( "Excute Error" );
		}
	}	
}

function __NgbEvent( _Name )
{
	// State
	this.k_nEventState_notRaised = 1;
	this.k_nEventState_raised = 2;
	this.k_nEventState_paused = 3;
	this.k_nEventState_canceled = 4;

	this.k_nEventHandlingType_Handler = 1;
	this.k_nEventHandlingType_Command = 2;

	this.State = this.k_nEventState_notRaised;
	this.Name = _Name;
	this.arg = null;
	this.Command = new Array();
	
	this.RaiseEvent = function( arg )
	{
		this.State = this.k_nEventState_raised;
		this.arg = arg;
		this.Execute();
	}

	this.AddHandler = function( _Command, arg )
	{
		this.Command[ this.Command.length ] = new __NgbCommand( this.k_nEventHandlingType_Handler, _Command, arg );
		this.Execute();
	}
	
	this.AddCommand = function( _Command, arg )
	{
		this.Command[ this.Command.length ] = new __NgbCommand( this.k_nEventHandlingType_Command, _Command, arg );
		this.Execute();
	}
	
	this.Execute = function()
	{
		if( this.State == this.k_nEventState_raised )
		{
			for( var i = 0 ; i < this.Command.length ; i++ )
			{
				if( this.Command[ i ].Type == this.k_nEventHandlingType_Handler ||
					( this.Command[ i ].Type == this.k_nEventHandlingType_Command && this.Command[ i ].nExecuteCount == 0 ) )
					this.Command[ i ].Execute( this.arg );
			}
		}
	}
}

var NgbEVM = new function __NgbEVM()
{
	// Type
	this.k_nEventType_immediately = 0;
	this.k_nEventType_onPageStart = 1;
	this.k_nEventType_onPageEnd = 2;
	this.k_nEventType_onLoad = 3;
	this.k_nEventType_onUnload = 4;
	this.k_nEventType_onSubmit = 5;

	// For Auth Syste
	this.k_nEventType_onRefreshNoteBox = 6;
	
	this.Event = new Array();
	this.Event[ this.k_nEventType_immediately ]				= new __NgbEvent( "k_nEventType_immediately" );
	this.Event[ this.k_nEventType_onPageStart ]				= new __NgbEvent( "k_nEventType_onPageStart" );
	this.Event[ this.k_nEventType_onPageEnd ]				= new __NgbEvent( "k_nEventType_onPageEnd" );
	this.Event[ this.k_nEventType_onLoad ]					= new __NgbEvent( "k_nEventType_onLoad" );
	this.Event[ this.k_nEventType_onUnload ]					= new __NgbEvent( "k_nEventType_onUnload" );
	this.Event[ this.k_nEventType_onSubmit ]					= new __NgbEvent( "k_nEventType_onSubmit" );
	this.Event[ this.k_nEventType_onRefreshNoteBox ]			= new __NgbEvent( "k_nEventType_onRefreshNoteBox" );
	
	this.AddHandler = function( nEventType, delegator /*, argument list... */ )
	{
		var arg = new Array();
		for( var i = 2 ; i < arguments.length ; i++ )
			arg [ i - 2 ] = arguments[ i ];

		if( !isNaN( nEventType ) )
			this.Event[ nEventType ].AddHandler( delegator, arg );
		else
			NgbDebug.Print( 'Invalid Event Type : Event.AddHandler - ' + nEventType );
	}
	
	this.AddCommand = function( nEventType, delegator /*, argument list... */ )
	{
		var arg = new Array();
		for( var i = 2 ; i < arguments.length ; i++ )
			arg [ i - 2 ] = arguments[ i ];

		if( !isNaN( nEventType ) )
			this.Event[ nEventType ].AddCommand( delegator, arg );
		else
			NgbDebug.Print( 'Invalid Event Type : Event.AddCommand - ' + nEventType );
	}
	
	this.ReplaceEventHandlerHelper = function( /*function*/ fnEventHandler, /*string*/ strPreJavascriptCode, /*string*/ strPostJavascriptCode )
	{
		var strEventHandlerJavascriptCode = "";
		if ( fnEventHandler )
		{
			strEventHandlerJavascriptCode = fnEventHandler.toString();
			strEventHandlerJavascriptCode = strEventHandlerJavascriptCode.slice( strEventHandlerJavascriptCode.indexOf( "{" ) + 1, -1 );
		}
		
		return new Function( strPreJavascriptCode + strEventHandlerJavascriptCode + strPostJavascriptCode );
	}
	
	this.ReplaceEventHandler = function()
	{
		document.body.onload = this.ReplaceEventHandlerHelper( document.body.onload, "", "return NgbEVM.RaiseEvent( NgbEVM.k_nEventType_onLoad );" );
		document.body.onunload = this.ReplaceEventHandlerHelper( document.body.onunload, "", "return NgbEVM.RaiseEvent( NgbEVM.k_nEventType_onUnload );" );
	}
	
	this.GetEventTypeName = function( nEventType )
	{
		return this.Event[ nEventType ].Name;
	}
	
	this.RaiseEvent = function( nEventType )
	{
		try
		{
			NgbDebug.print( this.GetEventTypeName( nEventType ) );
		}
		catch( e ) {}
		
		var arg = new Array();
		for( var i = 1 ; i < arguments.length ; i++ )
			arg [ i - 1 ] = arguments[ i ];

		if( !isNaN( nEventType ) )
			this.Event[ nEventType ].RaiseEvent( arg );
		else
			NgbDebug.Print( 'Invalid Event Type : Event.RaiseEvent - ' + nEventType );
	}
}



