import class gameuiChatBoxGameController extends inkHUDGameController
{
	private var m_player : weak< gamePuppetBase >;
	private var m_chatBoxBlackboardId : CallbackHandle;
	private editable var m_chatBox : inkWidgetRef;
	private editable var m_enteredText : inkTextInputRef;
	private var m_chatBoxOpen : Bool;
	private var m_recentChatsShown : array< weak< inkWidget > >;
	private editable var m_recentContainer : weak< inkVerticalPanel >;
	private editable var m_historyContainer : weak< inkVerticalPanel >;
	private var m_chatHistory : array< ChatBoxText >;
	private var m_lastChatId : Int32;
	private var maxChatsDisplayed : Int32;
	default maxChatsDisplayed = 7;
	private var maxChatHistory : Int32;
	default maxChatHistory = 100;

	protected event OnInitialize()
	{
		var chatBoxBB : IBlackboard;
		m_chatBoxOpen = false;
		m_lastChatId = -1;
		m_player = ( ( gamePuppetBase )( GetOwnerEntity() ) );
		m_player.RegisterInputListener( this, 'OpenChatBox' );
		m_player.RegisterInputListener( this, 'EnterChat' );
		m_player.RegisterInputListener( this, 'UI_Cancel' );
		chatBoxBB = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_ChatBox );
		m_chatBoxBlackboardId = chatBoxBB.RegisterListenerVariant( GetAllBlackboardDefs().UI_ChatBox.TextList, this, 'OnChatAdded' );
		SetMaxEnteredChars( ( ( weak< weak< inkTextInput > > )( inkTextInputRef.Get( m_enteredText ) ) ) );
		inkWidgetRef.SetVisible( m_chatBox, false );
		m_recentContainer = ( ( inkVerticalPanel )( GetWidget( 'RecentHolder/Recent' ) ) );
		m_historyContainer = ( ( inkVerticalPanel )( GetWidget( 'ChatBox/HistoryHolder/History' ) ) );
	}

	protected event OnChatAdded( value : Variant )
	{
		var chatList : array< ChatBoxText >;
		var i : Int32;
		chatList = ( ( array< ChatBoxText > )value );
		for( i = 0; i < chatList.Size(); i += 1 )
		{
			if( chatList[ i ].id > m_lastChatId )
			{
				m_lastChatId = chatList[ i ].id;
				m_chatHistory.Insert( 0, chatList[ i ] );
				if( m_chatHistory.Size() > maxChatHistory )
				{
					m_chatHistory.PopBack();
				}
				DisplayChat( chatList[ i ] );
			}
		}
		if( m_chatBoxOpen )
		{
			ShowHistory();
		}
	}

	private function DisplayChat( const chatBoxText : ref< ChatBoxText > )
	{
		var chatPanel : weak< inkWidget >;
		var controller : weak< TextSectionLogicController >;
		chatPanel = SpawnFromLocal( m_recentContainer, 'TextSection' );
		controller = ( ( TextSectionLogicController )( chatPanel.GetController() ) );
		controller.Show( chatBoxText );
		controller.RegisterToCallback( 'OnReadyToRemove', this, 'OnHideRecentChat' );
		controller.StartFadeOut();
		m_recentChatsShown.Insert( 0, chatPanel );
		if( m_recentChatsShown.Size() > maxChatsDisplayed )
		{
			chatPanel = m_recentChatsShown.PopBack();
			m_recentContainer.RemoveChild( chatPanel );
		}
	}

	private function DisplayHistory( const chatBoxText : ref< ChatBoxText > )
	{
		var chatPanel : weak< inkWidget >;
		var controller : weak< TextSectionLogicController >;
		chatPanel = SpawnFromLocal( m_historyContainer, 'TextSection' );
		controller = ( ( TextSectionLogicController )( chatPanel.GetController() ) );
		controller.Show( chatBoxText );
	}

	protected event OnHideRecentChat( chatItem : weak< inkWidget > )
	{
		m_recentChatsShown.Remove( chatItem );
		m_recentContainer.RemoveChild( chatItem );
	}

	protected event OnUninitialize()
	{
		var chatBoxBB : IBlackboard;
		if( m_chatBoxBlackboardId )
		{
			chatBoxBB = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_ChatBox );
			chatBoxBB.UnregisterListenerVariant( GetAllBlackboardDefs().UI_ChatBox.TextList, m_chatBoxBlackboardId );
		}
	}

	private import function UpdateInputContext( isChatBoxContext : Bool );
	private import function SetMaxEnteredChars( enteredText : weak< inkTextInput > );

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		var actionName : CName;
		var actionType : gameinputActionType;
		actionName = ListenerAction.GetName( action );
		actionType = ListenerAction.GetType( action );
		if( ( !( m_chatBoxOpen ) && actionName == 'OpenChatBox' ) && actionType == gameinputActionType.BUTTON_PRESSED )
		{
			ShowChatBox( true );
			ShowHistory();
		}
		else if( ( m_chatBoxOpen && actionName == 'EnterChat' ) && actionType == gameinputActionType.BUTTON_PRESSED )
		{
			SendChat();
			ShowChatBox( false );
		}
		else if( ( m_chatBoxOpen && actionName == 'UI_Cancel' ) && actionType == gameinputActionType.BUTTON_PRESSED )
		{
			ShowChatBox( false );
		}
	}

	private function ShowChatBox( show : Bool )
	{
		var enteredText : weak< inkTextInput >;
		var widgetToFocus : weak< inkWidget >;
		enteredText = ( ( weak< weak< inkTextInput > > )( inkTextInputRef.Get( m_enteredText ) ) );
		m_chatBoxOpen = show;
		enteredText.SetText( "" );
		inkWidgetRef.SetVisible( m_chatBox, show );
		widgetToFocus = ( ( show ) ? ( ( ( weak< weak< inkWidget > > )( inkTextInputRef.Get( m_enteredText ) ) ) ) : ( ( ( weak< weak< inkWidget > > )( NULL ) ) ) );
		RequestSetFocus( widgetToFocus );
		if( !( show ) )
		{
			m_historyContainer.RemoveAllChildren();
		}
		m_historyContainer.SetVisible( show );
		m_recentContainer.SetVisible( !( show ) );
		UpdateInputContext( show );
	}

	private function ShowHistory()
	{
		var i : Int32;
		m_historyContainer.RemoveAllChildren();
		for( i = Min( maxChatsDisplayed - 1, m_chatHistory.Size() - 1 ); i >= 0; i -= 1 )
		{
			DisplayHistory( m_chatHistory[ i ] );
		}
	}

	private function SendChat()
	{
		var textEntered : String;
		textEntered = ( ( weak< weak< inkTextInput > > )( inkTextInputRef.Get( m_enteredText ) ) ).GetText();
		if( textEntered != "" )
		{
			GameInstance.GetGameRulesSystem( GetGameInstance() ).SendChat( textEntered );
		}
	}

}

class TextSectionLogicController extends inkLogicController
{
	private var m_rootWidget : weak< inkWidget >;
	private var m_textWidget : weak< inkText >;
	private var m_showAnimProxy : inkAnimProxy;

	protected event OnInitialize()
	{
		m_rootWidget = GetRootWidget();
		m_textWidget = ( ( inkText )( GetWidget( 'Text' ) ) );
		m_rootWidget.SetAnchorPoint( Vector2( 0.5, 0.5 ) );
		SetActive( false );
	}

	protected event OnUninitialize() {}

	private function SetActive( active : Bool )
	{
		m_rootWidget.SetVisible( active );
	}

	public function Show( const chatBoxText : ref< ChatBoxText > )
	{
		m_textWidget.SetText( chatBoxText.text );
		m_textWidget.SetTintColor( chatBoxText.color );
		SetActive( true );
	}

	public function StartFadeOut()
	{
		m_showAnimProxy = PlayLibraryAnimation( 'TextFade' );
		m_showAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnHide' );
	}

	protected event OnHide( anim : inkAnimProxy )
	{
		SetActive( false );
		CallCustomCallback( 'OnReadyToRemove' );
	}

}

