import struct gameuiMountedWeaponTarget
{
	import var weaponIndex : Int32;
	import var targetLocation : Vector4;
}

import class gameuiDriverCombatMountedPowerWeaponCrosshairGameController extends gameuiCrosshairBaseGameController
{
	private editable var m_reticleLeft : inkWidgetRef;
	private editable var m_reticleRight : inkWidgetRef;
	private editable var m_reticleStartingRange : Float;
	default m_reticleStartingRange = 3.f;
	private editable var m_defaultOpacity : Float;
	default m_defaultOpacity = 1.0f;
	private editable var m_reducedOpacity : Float;
	default m_reducedOpacity = 0.2f;
	private var m_weaponList : array< weak< WeaponObject > >;
	private var m_isTPP : Bool;
	private var m_uiActiveVehicleDataBlackboard : weak< IBlackboard >;
	private var m_psmCombatStateChangedCallback : CallbackHandle;
	private var m_uiActiveVehicleCameraChangedCallback : CallbackHandle;

	protected event OnPlayerAttach( player : GameObject )
	{
		super.OnPlayerAttach( player );
		m_uiActiveVehicleDataBlackboard = GameInstance.GetBlackboardSystem( player.GetGame() ).Get( GetAllBlackboardDefs().UI_ActiveVehicleData );
		m_uiActiveVehicleCameraChangedCallback = m_uiActiveVehicleDataBlackboard.RegisterListenerBool( GetAllBlackboardDefs().UI_ActiveVehicleData.IsTPPCameraOn, this, 'OnActiveVehicleCameraChanged', true );
		m_psmCombatStateChangedCallback = m_psmBlackboard.RegisterListenerInt( GetAllBlackboardDefs().PlayerStateMachine.Combat, this, 'OnPSMCombatStateChanged', true );
	}

	protected event OnPlayerDetach( player : GameObject )
	{
		super.OnPlayerDetach( player );
		if( m_uiActiveVehicleCameraChangedCallback )
		{
			m_uiActiveVehicleDataBlackboard.UnregisterListenerBool( GetAllBlackboardDefs().UI_ActiveVehicleData.IsTPPCameraOn, m_uiActiveVehicleCameraChangedCallback );
		}
		if( m_psmCombatStateChangedCallback )
		{
			m_psmBlackboard.UnregisterListenerInt( GetAllBlackboardDefs().PlayerStateMachine.Combat, m_psmCombatStateChangedCallback );
		}
	}

	protected event OnActiveVehicleCameraChanged( isTPP : Bool )
	{
		m_isTPP = isTPP;
		inkWidgetRef.SetVisible( m_reticleLeft, m_isTPP );
		inkWidgetRef.SetVisible( m_reticleRight, m_isTPP );
	}

	protected event OnPSMCombatStateChanged( value : Int32 )
	{
		var opacity : Float;
		opacity = ( ( value == ( ( Int32 )( gamePSMCombat.InCombat ) ) ) ? ( m_defaultOpacity ) : ( m_reducedOpacity ) );
		inkWidgetRef.SetOpacity( m_reticleLeft, opacity );
		inkWidgetRef.SetOpacity( m_reticleRight, opacity );
	}

	protected event OnPreIntro()
	{
		m_weaponList.Clear();
		TryGetWeaponObjectList();
		super.OnPreIntro();
	}

	protected export function UpdateTranslation( uiScreenResolution : Vector2 )
	{
		var uiWidgetResolution : Vector2;
		var mountedWeaponTargetList : array< gameuiMountedWeaponTarget >;
		var currentRelativeWorldPosition, mountedWeaponTargetRelativeWorldPosition : Vector4;
		var ratio : Vector2;
		var scale : Vector2;
		var projection : Vector2;
		var position : Vector2;
		var reticle : inkWidgetRef;
		var currentAngle, minAngle : Float;
		var i, j : Int32;
		uiWidgetResolution = Vector2( 3840.0, 2160.0 );
		if( m_isTPP )
		{
			mountedWeaponTargetList = ( ( array< gameuiMountedWeaponTarget > )( m_uiActiveVehicleDataBlackboard.GetVariant( GetAllBlackboardDefs().UI_ActiveVehicleData.MountedWeaponsTargets ) ) );
			if( mountedWeaponTargetList.Size() > 0 )
			{
				ratio.X = uiWidgetResolution.X / uiScreenResolution.X;
				ratio.Y = uiWidgetResolution.Y / uiScreenResolution.Y;
				if( ratio.X > ratio.Y )
				{
					scale.X = 1.0;
					scale.Y = ratio.X / ratio.Y;
				}
				else
				{
					scale.X = ratio.Y / ratio.X;
					scale.Y = 1.0;
				}
				for( i = 0; i < mountedWeaponTargetList.Size(); i += 1 )
				{
					reticle = ( ( mountedWeaponTargetList[ i ].weaponIndex == 0 ) ? ( m_reticleLeft ) : ( m_reticleRight ) );
					inkWidgetRef.SetVisible( reticle, false );
					if( TryGetWeaponObjectList() )
					{
						minAngle = 360.0;
						mountedWeaponTargetRelativeWorldPosition = Vector4();
						for( j = 0; j < m_weaponList.Size(); j += 1 )
						{
							currentRelativeWorldPosition = mountedWeaponTargetList[ i ].targetLocation - m_weaponList[ j ].GetWorldPosition();
							currentAngle = Vector4.GetAngleBetween( m_weaponList[ j ].GetWorldForward(), mountedWeaponTargetRelativeWorldPosition );
							if( currentAngle < minAngle )
							{
								minAngle = currentAngle;
								mountedWeaponTargetRelativeWorldPosition = currentRelativeWorldPosition;
							}
						}
						if( Vector4.Length( mountedWeaponTargetRelativeWorldPosition ) >= m_reticleStartingRange )
						{
							inkWidgetRef.SetVisible( reticle, true );
							projection = ProjectWorldToScreen( mountedWeaponTargetList[ i ].targetLocation );
							position.X = ( ( uiWidgetResolution.X * 0.5 ) * projection.X ) * scale.X;
							position.Y = ( ( ( uiWidgetResolution.Y * 0.5 ) * projection.Y ) * -1.0 ) * scale.Y;
							inkWidgetRef.SetTranslation( reticle, position );
						}
					}
				}
			}
		}
	}

	public export override function GetIntroAnimation( firstEquip : Bool ) : inkAnimProxy
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( 0.0 );
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetDuration( 0.25 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		return m_rootWidget.PlayAnimation( anim );
	}

	public export override function GetOutroAnimation() : inkAnimProxy
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( 1.0 );
		alphaInterpolator.SetEndTransparency( 0.0 );
		alphaInterpolator.SetDuration( 0.25 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		return m_rootWidget.PlayAnimation( anim );
	}

	protected override function OnState_Aim()
	{
		m_rootWidget.SetVisible( true );
	}

	private function TryGetWeaponObjectList() : Bool
	{
		var vehicle : weak< VehicleObject >;
		if( m_weaponList.Size() > 0 )
		{
			return true;
		}
		VehicleComponent.GetVehicle( m_playerPuppet.GetGame(), m_playerPuppet.GetEntityID(), vehicle );
		vehicle.GetActiveWeapons( m_weaponList );
		return m_weaponList.Size() > 0;
	}

}

