class Crosshair_Melee_Knife extends gameuiCrosshairBaseGameController
{
	private editable var m_targetColorChange : inkWidgetRef;
	private editable var m_leftPart : inkWidgetRef;
	private editable var m_rightPart : inkWidgetRef;
	private editable var m_topPart : inkWidgetRef;
	private editable var m_botPart : inkWidgetRef;
	private var m_chargeBar : weak< inkCanvas >;
	private var m_chargeBarFG : weak< inkRectangle >;
	private var m_throwingKnifeResourcePoolListener : ThrowingKnifeResourcePoolListener;
	private var m_weaponID : EntityID;
	private var m_weaponBBID : CallbackHandle;
	private var m_meleeWeaponState : gamePSMMeleeWeapon;
	protected var m_animProxy : inkAnimProxy;
	protected var m_animOptions : inkAnimOptions;
	protected var m_isCrosshairAnimationOpen : Bool;
	private var m_preloaderThinL : weak< inkImage >;
	private var m_preloaderThinR : weak< inkImage >;
	private var m_preloaderThickL : weak< inkImage >;
	private var m_preloaderThickR : weak< inkImage >;
	private var m_preloader : weak< inkCanvas >;

	protected event OnInitialize()
	{
		super.OnInitialize();
		m_chargeBar = ( ( inkCanvas )( GetWidget( 'chargeBar' ) ) );
		m_chargeBarFG = ( ( inkRectangle )( GetWidget( 'chargeBar/chargeBarFG' ) ) );
		m_preloaderThinL = ( ( inkImage )( GetWidget( 'preloader/thinL/thinL' ) ) );
		m_preloaderThinR = ( ( inkImage )( GetWidget( 'preloader/thinR/thinR' ) ) );
		m_preloaderThickL = ( ( inkImage )( GetWidget( 'preloader/thickL/thickL' ) ) );
		m_preloaderThickR = ( ( inkImage )( GetWidget( 'preloader/thickR/thickR' ) ) );
		m_preloader = ( ( inkCanvas )( GetWidget( 'preloader' ) ) );
	}

	protected event OnPlayerAttach( playerPuppet : GameObject )
	{
		var playerSMBB : IBlackboard;
		playerSMBB = GetPSMBlackboard( playerPuppet );
		m_weaponBBID = playerSMBB.RegisterDelayedListenerInt( GetAllBlackboardDefs().PlayerStateMachine.MeleeWeapon, this, 'OnPSMMeleeWeaponStateChanged' );
		OnPSMMeleeWeaponStateChanged( playerSMBB.GetInt( GetAllBlackboardDefs().PlayerStateMachine.MeleeWeapon ) );
		m_animOptions.loopType = inkanimLoopType.None;
		m_animOptions.loopInfinite = false;
	}

	protected event OnPlayerDetach( playerPuppet : GameObject )
	{
		var playerSMBB : IBlackboard;
		if( m_weaponBBID )
		{
			playerSMBB = GetPSMBlackboard( playerPuppet );
			playerSMBB.UnregisterDelayedListener( GetAllBlackboardDefs().PlayerStateMachine.MeleeWeapon, m_weaponBBID );
		}
	}

	protected event OnPSMMeleeWeaponStateChanged( value : Int32 )
	{
		var oldState, newState : gamePSMMeleeWeapon;
		oldState = m_meleeWeaponState;
		newState = ( ( gamePSMMeleeWeapon )( value ) );
		if( oldState != newState )
		{
			m_meleeWeaponState = newState;
			UpdateThrowCrosshair();
		}
	}

	protected function UpdateThrowCrosshair()
	{
		if( m_meleeWeaponState == gamePSMMeleeWeapon.Targeting )
		{
			GetRootWidget().SetState( 'default' );
			if( !( m_isCrosshairAnimationOpen ) )
			{
				m_animProxy = PlayLibraryAnimation( 'throw_intro', m_animOptions );
				m_isCrosshairAnimationOpen = true;
			}
		}
		else if( m_meleeWeaponState == gamePSMMeleeWeapon.ThrowAttack )
		{
			GetRootWidget().SetState( 'knifeReloading' );
			if( m_isCrosshairAnimationOpen )
			{
				m_animProxy = PlayLibraryAnimation( 'throw_outro', m_animOptions );
				m_isCrosshairAnimationOpen = false;
			}
		}
		else
		{
			GetRootWidget().SetState( 'default' );
			if( m_isCrosshairAnimationOpen )
			{
				m_animProxy = PlayLibraryAnimation( 'throw_outro', m_animOptions );
				m_isCrosshairAnimationOpen = false;
			}
		}
	}

	protected event OnPreIntro()
	{
		var statPoolsSystem : StatPoolsSystem;
		var playerObject : GameObject;
		var weaponObject : ItemObject;
		weaponObject = GetWeaponItemObject();
		playerObject = ( ( GameObject )( GetOwnerEntity() ) );
		statPoolsSystem = GameInstance.GetStatPoolsSystem( playerObject.GetGame() );
		if( weaponObject && statPoolsSystem )
		{
			m_weaponID = weaponObject.GetEntityID();
			if( statPoolsSystem.IsStatPoolAdded( m_weaponID, gamedataStatPoolType.ThrowRecovery ) )
			{
				m_throwingKnifeResourcePoolListener = new ThrowingKnifeResourcePoolListener;
				SetReloadBarVisible( false );
				m_throwingKnifeResourcePoolListener.Bind( this, false );
				statPoolsSystem.RequestRegisteringListener( m_weaponID, gamedataStatPoolType.ThrowRecovery, m_throwingKnifeResourcePoolListener );
			}
		}
		super.OnPreIntro();
	}

	protected event OnUninitialize()
	{
		if( m_throwingKnifeResourcePoolListener && GetPlayerControlledObject() )
		{
			GameInstance.GetStatPoolsSystem( GetPlayerControlledObject().GetGame() ).RequestUnregisteringListener( m_weaponID, gamedataStatPoolType.ThrowRecovery, m_throwingKnifeResourcePoolListener );
			m_throwingKnifeResourcePoolListener = NULL;
		}
	}

	protected event OnPreOutro()
	{
		if( m_throwingKnifeResourcePoolListener && GetPlayerControlledObject() )
		{
			GameInstance.GetStatPoolsSystem( GetPlayerControlledObject().GetGame() ).RequestUnregisteringListener( m_weaponID, gamedataStatPoolType.ThrowRecovery, m_throwingKnifeResourcePoolListener );
			m_throwingKnifeResourcePoolListener = NULL;
		}
		super.OnPreOutro();
	}

	public virtual function SetReloadBar( percentage : Float )
	{
		m_preloaderThinL.SetRotation( percentage * -1.79999995 );
		m_preloaderThinR.SetRotation( percentage * 1.79999995 );
		m_preloaderThickL.SetRotation( percentage * 1.79999995 );
		m_preloaderThickR.SetRotation( percentage * -1.79999995 );
	}

	public 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 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 event OnBulletSpreadChanged( spread : Vector2 )
	{
		super.OnBulletSpreadChanged( spread );
		inkWidgetRef.SetMargin( m_leftPart, inkMargin( -( spread.X ), -( spread.Y ), 0.0, 0.0 ) );
		inkWidgetRef.SetMargin( m_rightPart, inkMargin( spread.X, -( spread.X ), 0.0, 0.0 ) );
		inkWidgetRef.SetMargin( m_topPart, inkMargin( -( spread.X ), spread.Y, 0.0, 0.0 ) );
		inkWidgetRef.SetMargin( m_botPart, inkMargin( spread.X, spread.Y, 0.0, 0.0 ) );
	}

	protected override function ApplyCrosshairGUIState( state : CName, aimedAtEntity : Entity )
	{
		inkWidgetRef.SetState( m_targetColorChange, state );
		inkWidgetRef.SetState( m_leftPart, state );
		inkWidgetRef.SetState( m_rightPart, state );
		inkWidgetRef.SetState( m_topPart, state );
		inkWidgetRef.SetState( m_botPart, state );
	}

	public function PlayReloadBarFadeAnimation( isFadeIn : Bool )
	{
		var animOptions : inkAnimOptions;
		animOptions.loopType = inkanimLoopType.None;
		animOptions.loopCounter = 1;
		if( isFadeIn )
		{
			m_animProxy = PlayLibraryAnimation( 'reload_start', animOptions );
		}
		else
		{
			m_animProxy.GotoStartAndStop();
			m_animProxy = PlayLibraryAnimation( 'reload_end', animOptions );
		}
	}

	public function SetReloadBarVisible( set : Bool )
	{
		m_preloader.SetVisible( set );
	}

	protected function ShowCrosshairFromState( show : Bool )
	{
		GetRootWidget().SetOpacity( ( ( show ) ? ( 1.0 ) : ( 0.0 ) ) );
	}

	protected override function OnState_Safe()
	{
		ShowCrosshairFromState( true );
	}

	protected override function OnState_Scanning()
	{
		ShowCrosshairFromState( false );
	}

	protected override function OnState_GrenadeCharging()
	{
		ShowCrosshairFromState( false );
	}

	protected override function OnState_HipFire()
	{
		ShowCrosshairFromState( true );
	}

	protected override function OnState_Reload()
	{
		ShowCrosshairFromState( true );
	}

	protected override function OnState_Aim()
	{
		ShowCrosshairFromState( true );
	}

	protected override function OnState_Sprint()
	{
		ShowCrosshairFromState( true );
	}

	protected override function OnState_LeftHandCyberware()
	{
		ShowCrosshairFromState( false );
	}

	public function GetFadeOutAnimation() : inkAnimDef
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( 1.0 );
		alphaInterpolator.SetEndTransparency( 0.0 );
		alphaInterpolator.SetDuration( 0.5 );
		alphaInterpolator.SetType( inkanimInterpolationType.Sinusoidal );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyInOut );
		anim.AddInterpolator( alphaInterpolator );
		return anim;
	}

	public function GetFadeInAnimation() : inkAnimDef
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( 0.0 );
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetDuration( 0.15000001 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		return anim;
	}

}

class ThrowingKnifeResourcePoolListener extends ScriptStatPoolsListener
{
	private var m_Crosshair : weak< Crosshair_Melee_Knife >;
	private var m_shouldDisplayBar : Bool;
	private var evt : ThrowingKnifeReloadFinishedCrosshairEvent;

	public function Bind( crosshair : weak< Crosshair_Melee_Knife >, shouldDisplayBar : Bool )
	{
		m_Crosshair = crosshair;
		m_shouldDisplayBar = false;
	}

	public override function OnStatPoolValueChanged( oldValue : Float, newValue : Float, percToPoints : Float )
	{
		if( ( AbsF( newValue ) - oldValue ) < 2.0 )
		{
			m_Crosshair.SetReloadBar( newValue );
		}
		else
		{
			m_Crosshair.PlayReloadBarFadeAnimation( false );
		}
		if( !( m_shouldDisplayBar ) && ( newValue <= 99.0 ) )
		{
			m_Crosshair.SetReloadBarVisible( true );
			m_Crosshair.PlayReloadBarFadeAnimation( true );
			m_shouldDisplayBar = true;
		}
	}

	protected event OnStatPoolMaxValueReached( value : Float )
	{
		m_shouldDisplayBar = false;
		m_Crosshair.PlayReloadBarFadeAnimation( false );
	}

	protected event OnStatPoolMinValueReached( value : Float )
	{
		m_shouldDisplayBar = true;
		m_Crosshair.PlayReloadBarFadeAnimation( true );
		m_Crosshair.SetReloadBar( value );
		m_Crosshair.SetReloadBarVisible( true );
	}

}

class ThrowingKnifeReloadFinishedCrosshairEvent extends Event
{
}

