class HubMenuInitData extends IScriptable
{
	var m_menuName : CName;
	var m_submenuName : CName;
	var m_combatRestriction : Bool;
	var m_userData : IScriptable;
}

class StartHubMenuEvent extends Event
{
	var m_initData : HubMenuInitData;

	public function SetStartMenu( menuName : CName, optional submenuName : CName, optional userData : IScriptable )
	{
		m_initData = new HubMenuInitData;
		m_initData.m_menuName = menuName;
		m_initData.m_submenuName = submenuName;
		m_initData.m_userData = userData;
	}

}

class ForceCloseHubMenuEvent extends Event
{
}

class MenuScenario_Idle extends inkMenuScenario
{

	protected event OnEnterScenario( prevScenario : CName, userData : IScriptable )
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( prevScenario != '' )
		{
			menuState.CloseAllMenus();
			menuState.ShowMenus( false );
		}
		QueueEvent( new UIInGameNotificationRemoveEvent );
	}

	protected event OnBlockHub()
	{
		GetMenusState().SetHubMenuBlocked( true );
	}

	protected event OnUnlockHub()
	{
		GetMenusState().SetHubMenuBlocked( false );
	}

	protected event OnLeaveScenario( nextScenario : CName )
	{
		QueueEvent( new UIInGameNotificationRemoveEvent );
		GetMenusState().ShowMenus( true );
	}

	protected event OnOpenPauseMenu()
	{
		SwitchToScenario( 'MenuScenario_PauseMenu' );
	}

	protected event OnOpenHubMenu()
	{
		var notificationEvent : UIInGameNotificationEvent;
		if( !( GetMenusState().IsHubMenuBlocked() ) )
		{
			SwitchToScenario( 'MenuScenario_HubMenu' );
		}
		else
		{
			QueueEvent( new UIInGameNotificationRemoveEvent );
			notificationEvent = new UIInGameNotificationEvent;
			notificationEvent.m_notificationType = UIInGameNotificationType.CombatRestriction;
			QueueEvent( notificationEvent );
		}
	}

	protected event OnOpenRadialHubMenu()
	{
		var notificationEvent : UIInGameNotificationEvent;
		if( !( GetMenusState().IsHubMenuBlocked() ) )
		{
			SwitchToScenario( 'MenuScenario_RadialHubMenu' );
		}
		else
		{
			QueueEvent( new UIInGameNotificationRemoveEvent );
			notificationEvent = new UIInGameNotificationEvent;
			notificationEvent.m_notificationType = UIInGameNotificationType.CombatRestriction;
			QueueEvent( notificationEvent );
		}
	}

	protected event OnOpenHubMenu_InitData( userData : IScriptable )
	{
		var notificationEvent : UIInGameNotificationEvent;
		if( !( GetMenusState().IsHubMenuBlocked() ) )
		{
			SwitchToScenario( 'MenuScenario_HubMenu', userData );
		}
		else
		{
			QueueEvent( new UIInGameNotificationRemoveEvent );
			notificationEvent = new UIInGameNotificationEvent;
			notificationEvent.m_notificationType = UIInGameNotificationType.CombatRestriction;
			QueueEvent( notificationEvent );
		}
	}

	protected event OnOpenRadialHubMenu_InitData( userData : IScriptable )
	{
		var notificationEvent : UIInGameNotificationEvent;
		if( !( GetMenusState().IsHubMenuBlocked() ) )
		{
			SwitchToScenario( 'MenuScenario_RadialHubMenu', userData );
		}
		else
		{
			QueueEvent( new UIInGameNotificationRemoveEvent );
			notificationEvent = new UIInGameNotificationEvent;
			notificationEvent.m_notificationType = UIInGameNotificationType.CombatRestriction;
			QueueEvent( notificationEvent );
		}
	}

	protected event OnNetworkBreachBegin()
	{
		SwitchToScenario( 'MenuScenario_NetworkBreach' );
	}

	protected event OnShowDeathMenu()
	{
		SwitchToScenario( 'MenuScenario_DeathMenu' );
	}

	protected event OnShowStorageMenu()
	{
		SwitchToScenario( 'MenuScenario_Storage' );
	}

	protected event OnOpenFastTravel()
	{
		SwitchToScenario( 'MenuScenario_FastTravel' );
	}

	protected event OnOpenWardrobeMenu( userData : IScriptable )
	{
		SwitchToScenario( 'MenuScenario_Wardrobe', userData );
	}

	protected event OnArcadeMinigameBegin( userData : IScriptable )
	{
		SwitchToScenario( 'MenuScenario_ArcadeMinigame', userData );
	}

	protected event OnOpenTimeSkip()
	{
		SwitchToScenario( 'MenuScenario_TimeSkip' );
	}

}

class MenuScenario_BaseMenu extends inkMenuScenario
{
	protected var m_currMenuName : CName;
	protected var m_currUserData : IScriptable;
	protected var m_currSubMenuName : CName;
	protected var m_prevMenuName : CName;

	protected event OnLeaveScenario( nextScenario : CName )
	{
		CloseMenu();
	}

	protected event OnBack()
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( m_currSubMenuName != '' )
		{
			if( !( menuState.DispatchEvent( m_currSubMenuName, 'OnBack' ) ) )
			{
				CloseSubMenu();
			}
		}
		else if( m_currMenuName != '' )
		{
			if( !( menuState.DispatchEvent( m_currMenuName, 'OnBack' ) ) )
			{
				GotoIdleState();
			}
		}
	}

	protected function OpenMenu( menuName : CName, optional userData : IScriptable, optional context : ScreenDisplayContext )
	{
		GetMenusState().OpenMenu( menuName, userData );
		SetDisplayContext( context );
	}

	protected function SwitchMenu( menuName : CName, optional userData : IScriptable, optional context : ScreenDisplayContext )
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( m_currMenuName != '' )
		{
			menuState.DispatchEvent( m_currMenuName, 'OnCloseMenu' );
			menuState.CloseMenu( m_currMenuName );
		}
		m_currMenuName = menuName;
		m_currUserData = userData;
		menuState.OpenMenu( m_currMenuName, userData );
		SetDisplayContext( context );
	}

	private function SetDisplayContext( context : ScreenDisplayContext )
	{
		if( context != ScreenDisplayContext.Default )
		{
			if( m_currMenuName != '' )
			{
				GetMenusState().DispatchEvent( m_currMenuName, 'OnSetScreenDisplayContext', ScreenDisplayContextData.Make( context ) );
			}
		}
	}

	protected function CloseMenu()
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( m_currMenuName != '' )
		{
			menuState.DispatchEvent( m_currMenuName, 'OnCloseMenu' );
			menuState.CloseMenu( m_currMenuName );
			m_currMenuName = '';
		}
	}

	protected function OpenSubMenu( menuName : CName, optional userData : IScriptable )
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( m_currSubMenuName != '' )
		{
			menuState.DispatchEvent( m_currSubMenuName, 'OnCloseMenu' );
			menuState.CloseMenu( m_currSubMenuName );
		}
		m_currSubMenuName = menuName;
		menuState.OpenMenu( m_currSubMenuName, userData );
	}

	protected function CloseSubMenu()
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( m_currSubMenuName != '' )
		{
			menuState.DispatchEvent( m_currSubMenuName, 'OnCloseMenu' );
			menuState.CloseMenu( m_currSubMenuName );
			m_currSubMenuName = '';
		}
	}

	protected function SetContext( context : ScreenDisplayContext )
	{
		var menuState : weak< inkMenusState >;
		menuState = GetMenusState();
		if( m_currSubMenuName != '' )
		{
			menuState.DispatchEvent( m_currSubMenuName, 'OnCloseMenu' );
		}
	}

	protected virtual function GotoIdleState()
	{
		SwitchToScenario( 'MenuScenario_Idle' );
	}

}

class MenuScenario_CharacterCustomizationMirror extends MenuScenario_BaseMenu
{
	private var m_morphMenuUserData : MorphMenuUserData;

	protected event OnEnterScenario( prevScenario : CName, userData : IScriptable )
	{
		m_morphMenuUserData = ( ( MorphMenuUserData )( userData ) );
		if( m_morphMenuUserData )
		{
			m_morphMenuUserData.m_optionsListInitialized = false;
			m_morphMenuUserData.m_updatingFinalizedState = true;
		}
		m_currMenuName = 'character_customization_scenes';
		GetMenusState().OpenMenu( 'character_customization_scenes' );
	}

	protected event OnCCOPuppetReady()
	{
		var menuState : weak< inkMenusState >;
		m_currMenuName = 'character_customization';
		menuState = GetMenusState();
		menuState.OpenMenu( 'player_puppet' );
		menuState.OpenMenu( 'character_customization', m_morphMenuUserData );
	}

	protected event OnAccept()
	{
		GotoIdleState();
	}

	protected event OnBack() {}

	protected event OnCancel()
	{
		GotoIdleState();
	}

}

enum ScreenDisplayContext
{
	Default = 0,
	Vendor = 1,
	Storage = 2,
}

class ScreenDisplayContextData
{
	var Context : ScreenDisplayContext;

	public static function Make( context : ScreenDisplayContext ) : ScreenDisplayContextData
	{
		var instance : ScreenDisplayContextData;
		instance = new ScreenDisplayContextData;
		instance.Context = context;
		return instance;
	}

}

abstract class MenuUIUtils
{

	public static function RequestAutoSave( player : weak< GameObject >, optional delay : Float )
	{
		var evt : AutoSaveEvent;
		if( player == NULL )
		{
			return;
		}
		if( delay <= 0.0 )
		{
			GameInstance.GetAutoSaveSystem( player.GetGame() ).RequestCheckpoint();
		}
		else
		{
			evt = new AutoSaveEvent;
			evt.maxAttempts = 5;
			evt.isForced = true;
			GameInstance.GetDelaySystem( player.GetGame() ).DelayEvent( player, evt, delay, false );
		}
	}

}

