struct GameObjectScanStats
{
	var scannerData : scannerDataStructure;
}

import class scannerGameController extends inkHUDGameController
{
	private var m_bbWeaponInfo : weak< IBlackboard >;
	private var m_BraindanceBB : weak< IBlackboard >;
	private var m_bbWeaponEventId : CallbackHandle;
	private var m_BBID_BraindanceActive : CallbackHandle;
	private var m_scannerscannerObjectStatsId : CallbackHandle;
	private var m_scannerScannablesId : CallbackHandle;
	private var m_scannerCurrentProgressId : CallbackHandle;
	private var m_scannerCurrentStateId : CallbackHandle;
	private var m_scannerScannedObjectId : CallbackHandle;
	private var scannerData : scannerDataStructure;
	private import var currentTarget : EntityID;
	private var curObj : GameObjectScanStats;
	private var m_scannerBorderMain : weak< inkCompoundWidget >;
	private var m_scannerBorderController : weak< scannerBorderLogicController >;
	private var m_scannerProgressMain : weak< inkCompoundWidget >;
	private var m_scannerFullScreenOverlay : weak< inkWidget >;
	private var m_center_frame : weak< inkImage >;
	private var m_squares : array< weak< inkImage > >;
	private var m_squaresFilled : array< weak< inkImage > >;
	private var m_isUnarmed : Bool;
	private import var scanLock : Bool;
	private var isEnabled : Bool;
	private var isFinish : Bool;
	private var isScanned : Bool;
	private import var percentValue : Float;
	private import var oldPercentValue : Float;
	private var m_isBraindanceActive : Bool;
	private var m_border_show : inkAnimDef;
	private var m_center_show : inkAnimDef;
	private var m_center_hide : inkAnimDef;
	private var m_dots_show : inkAnimDef;
	private var m_dots_hide : inkAnimDef;
	private var m_BorderAnimProxy : inkAnimProxy;
	private var soundFinishedOn : CName;
	default soundFinishedOn = 'ui_generic_set_11_navigation';
	private var soundFinishedOff : CName;
	default soundFinishedOff = 'ui_generic_set_10_navigation';
	private var m_playerSpawnedCallbackID : Uint32;
	private var m_BBID_IsEnabledChange : CallbackHandle;
	private var m_gameInstance : GameInstance;
	private var m_isShown : Bool;
	private var m_playerPuppet : weak< GameObject >;

	protected event OnInitialize()
	{
		var uiBlackboard : IBlackboard;
		var rootWidget : weak< inkCompoundWidget >;
		m_isUnarmed = true;
		rootWidget = ( ( inkCompoundWidget )( GetRootWidget() ) );
		AsyncSpawnFromExternal( ( ( inkWidget )( rootWidget.GetWidget( 'border' ) ) ), R"base\gameplay\gui\widgets\scanning\scanner_hud.inkwidget", 'Root', this, 'OnScannerHudSpawned' );
		CreateAnimationTemplates();
		uiBlackboard = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_Scanner );
		m_scannerscannerObjectStatsId = uiBlackboard.RegisterDelayedListenerVariant( GetAllBlackboardDefs().UI_Scanner.scannerObjectStats, this, 'OnObjectData' );
		m_scannerScannablesId = uiBlackboard.RegisterDelayedListenerVariant( GetAllBlackboardDefs().UI_Scanner.Scannables, this, 'OnScannablesChange' );
		m_scannerCurrentProgressId = uiBlackboard.RegisterDelayedListenerFloat( GetAllBlackboardDefs().UI_Scanner.CurrentProgress, this, 'OnProgressChange' );
		m_scannerCurrentStateId = uiBlackboard.RegisterDelayedListenerVariant( GetAllBlackboardDefs().UI_Scanner.CurrentState, this, 'OnStateChanged' );
		m_scannerScannedObjectId = uiBlackboard.RegisterDelayedListenerEntityID( GetAllBlackboardDefs().UI_Scanner.ScannedObject, this, 'OnScannedObjectChanged' );
		ConnectToPlayerRelatedBlackboards( GetPlayerControlledObject() );
		m_bbWeaponInfo = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_ActiveWeaponData );
		m_bbWeaponEventId = m_bbWeaponInfo.RegisterDelayedListenerVariant( GetAllBlackboardDefs().UI_ActiveWeaponData.WeaponRecordID, this, 'OnWeaponSwap' );
		m_BraindanceBB = GetBlackboardSystem().Get( GetAllBlackboardDefs().Braindance );
		if( m_BraindanceBB )
		{
			m_BBID_BraindanceActive = m_BraindanceBB.RegisterDelayedListenerBool( GetAllBlackboardDefs().Braindance.IsActive, this, 'OnBraindanceToggle' );
		}
		OnIsEnabledChange( ( ( Int32 )( gamePSMVision.Default ) ) );
		m_gameInstance = ( ( GameObject )( GetOwnerEntity() ) ).GetGame();
	}

	protected event OnScannerHudSpawned( widget : inkWidget, userData : IScriptable )
	{
		var rootWidget : weak< inkCompoundWidget >;
		var i : Int32;
		rootWidget = ( ( inkCompoundWidget )( GetRootWidget() ) );
		m_scannerBorderMain = ( ( inkCompoundWidget )( widget ) );
		m_scannerBorderController = ( ( scannerBorderLogicController )( m_scannerBorderMain.GetController() ) );
		m_scannerFullScreenOverlay = ( ( inkWidget )( m_scannerBorderMain.GetWidget( 'fullscreenHeavyOverlay' ) ) );
		m_scannerProgressMain = ( ( inkCompoundWidget )( rootWidget.GetWidget( 'module' ) ) );
		m_center_frame = ( ( inkImage )( m_scannerBorderMain.GetWidget( 'crosshair\center_frame' ) ) );
		for( i = 0; i < 18; i += 1 )
		{
			m_squares.PushBack( ( ( inkImage )( m_scannerBorderMain.GetWidget( StringToName( "crosshair\dots_square\square" + IntToString( i + 1 ) ) ) ) ) );
			m_squaresFilled.PushBack( ( ( inkImage )( m_scannerBorderMain.GetWidget( StringToName( "crosshair\dots_filled\square" + IntToString( i + 1 ) ) ) ) ) );
		}
	}

	protected event OnUnitialize()
	{
		var uiBlackboard : IBlackboard;
		m_squares.Clear();
		m_squaresFilled.Clear();
		uiBlackboard = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_Scanner );
		uiBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_Scanner.scannerObjectStats, m_scannerscannerObjectStatsId );
		uiBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_Scanner.Scannables, m_scannerScannablesId );
		uiBlackboard.UnregisterListenerFloat( GetAllBlackboardDefs().UI_Scanner.CurrentProgress, m_scannerCurrentProgressId );
		uiBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_Scanner.CurrentState, m_scannerCurrentStateId );
		uiBlackboard.UnregisterListenerEntityID( GetAllBlackboardDefs().UI_Scanner.ScannedObject, m_scannerScannedObjectId );
		m_scannerBorderMain = NULL;
		m_scannerBorderController = NULL;
		m_scannerFullScreenOverlay = NULL;
		m_scannerProgressMain = NULL;
		m_center_frame = NULL;
		if( m_bbWeaponInfo )
		{
			m_bbWeaponInfo.UnregisterListenerVariant( GetAllBlackboardDefs().UI_ActiveWeaponData.WeaponRecordID, m_bbWeaponEventId );
		}
		if( m_BraindanceBB )
		{
			m_BraindanceBB.UnregisterDelayedListener( GetAllBlackboardDefs().Braindance.IsActive, m_BBID_BraindanceActive );
		}
		DisconnectFromPlayerRelatedBlackboards( GetPlayerControlledObject() );
	}

	protected event OnPlayerAttach( playerPuppet : GameObject )
	{
		var isFocusModeActive : Bool;
		ConnectToPlayerRelatedBlackboards( playerPuppet );
		m_playerPuppet = ( ( GameObject )( GetPlayerControlledObject() ) );
		isFocusModeActive = GetPSMBlackboard( playerPuppet ).GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vision ) == ( ( Int32 )( gamePSMVision.Focus ) );
		if( isFocusModeActive )
		{
			OnIsEnabledChange( ( ( Int32 )( gamePSMVision.Focus ) ) );
		}
	}

	protected event OnPlayerDetach( playerPuppet : GameObject )
	{
		if( isEnabled )
		{
			OnIsEnabledChange( ( ( Int32 )( gamePSMVision.Default ) ) );
		}
		DisconnectFromPlayerRelatedBlackboards( playerPuppet );
	}

	protected event OnBraindanceToggle( value : Bool )
	{
		m_isBraindanceActive = value;
		if( !( value ) )
		{
			ShowScanBorder( false );
		}
	}

	private function ConnectToPlayerRelatedBlackboards( playerPuppet : GameObject )
	{
		DisconnectFromPlayerRelatedBlackboards( playerPuppet );
		if( playerPuppet.IsControlledByLocalPeer() && !( m_BBID_IsEnabledChange ) )
		{
			m_BBID_IsEnabledChange = GetPSMBlackboard( playerPuppet ).RegisterDelayedListenerInt( GetAllBlackboardDefs().PlayerStateMachine.Vision, this, 'OnIsEnabledChange' );
		}
	}

	private function DisconnectFromPlayerRelatedBlackboards( playerPuppet : GameObject )
	{
		if( m_BBID_IsEnabledChange )
		{
			GetPSMBlackboard( playerPuppet ).UnregisterDelayedListener( GetAllBlackboardDefs().PlayerStateMachine.Vision, m_BBID_IsEnabledChange );
		}
	}

	protected event OnWeaponSwap( value : Variant )
	{
		m_isUnarmed = ( ( TweakDBID )value ) == TDBID.None();
	}

	private function CreateAnimationTemplates()
	{
		var alphaInterpolator : inkAnimTransparency;
		m_border_show = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetDuration( 0.5 );
		alphaInterpolator.SetStartTransparency( 0.0 );
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		m_border_show.AddInterpolator( alphaInterpolator );
		m_center_show = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetDuration( 0.5 );
		alphaInterpolator.SetStartTransparency( 0.2 );
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		m_center_show.AddInterpolator( alphaInterpolator );
		m_center_hide = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetDuration( 0.5 );
		alphaInterpolator.SetStartTransparency( 1.0 );
		alphaInterpolator.SetEndTransparency( 0.2 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		m_center_hide.AddInterpolator( alphaInterpolator );
		m_dots_show = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetDuration( 1.0 );
		alphaInterpolator.SetStartTransparency( 0.60000002 );
		alphaInterpolator.SetEndTransparency( 0.5 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		m_dots_show.AddInterpolator( alphaInterpolator );
		m_dots_hide = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetDuration( 1.0 );
		alphaInterpolator.SetStartTransparency( 0.60000002 );
		alphaInterpolator.SetEndTransparency( 0.2 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		m_dots_hide.AddInterpolator( alphaInterpolator );
	}

	private function ShowScanBorder( val : Bool )
	{
		m_scannerBorderMain.SetVisible( val );
		m_scannerBorderController.SetBraindanceMode( m_isBraindanceActive );
	}

	private function PlaySound( SoundEffect : CName )
	{
		var audioEvent : SoundPlayEvent;
		var player : PlayerPuppet;
		audioEvent = new SoundPlayEvent;
		audioEvent.soundName = SoundEffect;
		player = ( ( PlayerPuppet )( GetPlayerControlledObject() ) );
		player.QueueEvent( audioEvent );
	}

	private function ShowScanner( show : Bool )
	{
		var uiBlackboard : IBlackboard;
		if( m_isShown != show )
		{
			m_isShown = show;
			uiBlackboard = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_Scanner );
			uiBlackboard.SetBool( GetAllBlackboardDefs().UI_Scanner.UIVisible, show );
			if( show )
			{
				GameObjectEffectHelper.StartEffectEvent( m_playerPuppet, 'focus_mode' );
				GameInstance.GetUISystem( m_gameInstance ).RequestNewVisualState( 'inkScanningState' );
				GameInstance.GetRazerChromaEffectsSystem( m_gameInstance ).PlayAnimation( 'Scan', true );
			}
			else
			{
				GameObjectEffectHelper.BreakEffectLoopEvent( m_playerPuppet, 'focus_mode' );
				GameInstance.GetUISystem( m_gameInstance ).RestorePreviousVisualState( 'inkScanningState' );
				GameInstance.GetRazerChromaEffectsSystem( m_gameInstance ).StopAnimation( 'Scan' );
			}
		}
		m_scannerProgressMain.SetVisible( show );
		GetRootWidget().SetVisible( show );
	}

	protected event OnScannedObjectChanged( val : EntityID )
	{
		var id : EntityID;
		var chunksBB : IBlackboard;
		if( !( scanLock ) )
		{
			id = val;
			if( ( currentTarget != id ) || !( EntityID.IsDefined( id ) ) )
			{
				currentTarget = id;
				isFinish = false;
			}
			if( !( EntityID.IsDefined( id ) ) )
			{
				scannerData.entityName = "";
				scannerData.questEntries.Clear();
				chunksBB = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_ScannerModules );
				if( chunksBB )
				{
					chunksBB.ClearAllFields( true );
				}
			}
		}
	}

	protected event OnStateChanged( val : Variant )
	{
		var state : gameScanningState;
		state = ( ( gameScanningState )val );
		isScanned = state == gameScanningState.Complete || state == gameScanningState.ShallowComplete;
	}

	protected event OnObjectData( val : Variant )
	{
		var stats : GameObjectScanStats;
		if( !( scanLock ) )
		{
			stats = ( ( GameObjectScanStats )val );
			curObj = stats;
		}
	}

	protected event OnIsEnabledChange( val : Int32 )
	{
		if( val == ( ( Int32 )( gamePSMVision.Default ) ) )
		{
			ShowScanner( false );
			isEnabled = false;
			ShowScanBorder( false );
			m_scannerBorderMain.StopAllAnimations();
		}
		else if( val == ( ( Int32 )( gamePSMVision.Focus ) ) )
		{
			ShowScanBorder( true );
			ShowScanner( true );
			m_scannerBorderMain.PlayAnimation( m_border_show );
			isEnabled = true;
		}
	}

	private function AddQuestData( cat : CName, entry : CName, recordID : TweakDBID )
	{
		var questEntry : scannerQuestEntry;
		questEntry.categoryName = cat;
		questEntry.entryName = entry;
		questEntry.recordID = recordID;
		scannerData.questEntries.PushBack( questEntry );
	}

	private function OnProgressChange( val : Float )
	{
		percentValue = val;
		scanLock = val > 0.0;
	}

	private function OnScannablesChange( val : Variant )
	{
		var i : Int32;
		var scannables : array< ScanningTooltipElementData >;
		scannables = ( ( array< ScanningTooltipElementData > )val );
		scannerData.entityName = curObj.scannerData.entityName;
		scannerData.questEntries.Clear();
		for( i = 0; i < scannables.Size(); i += 1 )
		{
			AddQuestData( scannables[ i ].localizedName, scannables[ i ].localizedDescription, scannables[ i ].recordID );
		}
	}

}

