enum ECooldownIndicatorState
{
	Pooled = 0,
	Intro = 1,
	Filling = 2,
	Outro = 3,
}

class SingleCooldownManager extends inkLogicController
{
	private editable var m_sprite : inkImageRef;
	private editable var m_spriteBg : inkImageRef;
	private editable var m_icon : inkImageRef;
	private editable var m_type : ECooldownGameControllerMode;
	private editable var m_name : inkTextRef;
	private editable var m_desc : inkTextRef;
	private editable var m_timeRemaining : inkTextRef;
	private editable var m_stackCount : inkTextRef;
	private editable var m_fill : inkRectangleRef;
	private editable var m_outroDuration : Float;
	private var m_fullSizeValue : Vector2;
	private var m_initialDuration : Float;
	private var m_state : ECooldownIndicatorState;
	private var m_pool : inkCompoundRef;
	private var m_grid : inkCompoundRef;
	private var m_currentAnimProxy : inkAnimProxy;
	private var m_buffData : UIBuffInfo;
	private var m_defaultTimeRemainingText : String;
	private var excludedStatusEffect : TweakDBID;
	private var C_EXCLUDED_STATUS_EFFECT_NAME : String;
	default C_EXCLUDED_STATUS_EFFECT_NAME = "BaseStatusEffect.AlcoholDebuff";

	public function Init( pool : inkCompoundRef, grid : inkCompoundRef )
	{
		m_pool = pool;
		m_grid = grid;
		m_fullSizeValue = inkRectangleRef.GetSize( m_fill );
		m_state = ECooldownIndicatorState.Pooled;
		m_defaultTimeRemainingText = inkTextRef.GetText( m_timeRemaining );
		GetRootWidget().SetVisible( false );
	}

	public function ActivateCooldown( buffData : UIBuffInfo )
	{
		var effect : weak< StatusEffect_Record >;
		var effectUIData : weak< StatusEffectUIData_Record >;
		var textParams : inkTextParams;
		var i : Int32;
		excludedStatusEffect = TDBID.Create( C_EXCLUDED_STATUS_EFFECT_NAME );
		effect = TweakDBInterface.GetStatusEffectRecord( buffData.buffID );
		if( !( effect ) || ( effect.GetID() == excludedStatusEffect ) )
		{
			return;
		}
		effectUIData = effect.UiData();
		if( !( effectUIData ) )
		{
			return;
		}
		m_buffData = buffData;
		GetRootWidget().SetVisible( true );
		if( m_buffData.isBuff )
		{
			GetRootWidget().SetState( 'Buff' );
		}
		else
		{
			GetRootWidget().SetState( 'Debuff' );
		}
		inkTextRef.SetText( m_name, effectUIData.DisplayName() );
		inkTextRef.SetText( m_desc, effectUIData.Description() );
		inkTextRef.SetVisible( m_desc, IsStringValid( effectUIData.Description() ) );
		if( ( ( effectUIData.GetFloatValuesCount() > 0 ) || ( effectUIData.GetIntValuesCount() > 0 ) ) || ( effectUIData.GetNameValuesCount() > 0 ) )
		{
			textParams = new inkTextParams;
			for( i = 0; i < effectUIData.GetFloatValuesCount(); i += 1 )
			{
				textParams.AddNumber( "float_" + IntToString( i ), effectUIData.GetFloatValuesItem( i ) );
			}
			for( i = 0; i < effectUIData.GetIntValuesCount(); i += 1 )
			{
				textParams.AddNumber( "int_" + IntToString( i ), effectUIData.GetIntValuesItem( i ) );
			}
			for( i = 0; i < effectUIData.GetNameValuesCount(); i += 1 )
			{
				textParams.AddString( "name_" + IntToString( i ), GetLocalizedText( NameToString( effectUIData.GetNameValuesItem( i ) ) ) );
			}
			inkTextRef.SetTextParameters( m_desc, textParams );
		}
		SetTimeRemaining( m_buffData.timeRemaining );
		SetStackCount( ( ( Int32 )( m_buffData.stackCount ) ) );
		if( m_type == ECooldownGameControllerMode.COOLDOWNS )
		{
			InkImageUtils.RequestSetImage( this, m_spriteBg, "UIIcon." + effectUIData.IconPath() );
			InkImageUtils.RequestSetImage( this, m_sprite, "UIIcon." + effectUIData.IconPath() );
		}
		else
		{
			InkImageUtils.RequestSetImage( this, m_icon, "UIIcon." + effectUIData.IconPath() );
		}
		m_state = ECooldownIndicatorState.Intro;
		m_initialDuration = m_buffData.timeRemaining;
		if( m_initialDuration > m_outroDuration )
		{
			FillIntroAnimationStart();
		}
		else
		{
			FillOutroAnimationStart();
		}
		GetRootWidget().Reparent( ( ( weak< weak< inkCompoundWidget > > )( inkCompoundRef.Get( m_grid ) ) ) );
	}

	public function Update( timeLeft : Float, stackCount : Uint32 )
	{
		var updatedSize : Float;
		var fraction : Float;
		if( timeLeft <= 0.01 )
		{
			updatedSize = 0.0;
			GetRootWidget().SetVisible( false );
		}
		else
		{
			GetRootWidget().SetVisible( true );
			fraction = timeLeft / m_initialDuration;
			updatedSize = fraction;
		}
		inkImageRef.Get( m_sprite ).SetEffectParamValue( inkEffectType.LinearWipe, 'LinearWipe_0', 'transition', AbsF( updatedSize ) );
		SetTimeRemaining( timeLeft );
		SetStackCount( ( ( Int32 )( stackCount ) ) );
		if( timeLeft <= m_outroDuration )
		{
			FillOutroAnimationStart();
		}
	}

	private function SetStackCount( count : Int32 )
	{
		if( count <= 1 )
		{
			inkTextRef.SetVisible( m_stackCount, false );
		}
		else
		{
			inkTextRef.SetVisible( m_stackCount, true );
			inkTextRef.SetText( m_stackCount, IntToString( count ) );
		}
	}

	private function SetTimeRemaining( time : Float )
	{
		var textParams : inkTextParams;
		var gameTime : GameTime;
		var wholeNumber : Int32;
		var fraction : Int32;
		textParams = new inkTextParams;
		ConvertFloatToTime( time, gameTime, wholeNumber, fraction );
		if( GameTime.Minutes( gameTime ) <= 0 )
		{
			inkTextRef.SetText( m_timeRemaining, m_defaultTimeRemainingText );
			textParams.AddNumber( "value", wholeNumber );
			textParams.AddNumber( "millis", fraction );
			inkTextRef.SetTextParameters( m_timeRemaining, textParams );
		}
		else
		{
			inkTextRef.SetText( m_timeRemaining, "{TIME,time,mm:ss}" );
			textParams.AddTime( "TIME", gameTime );
			inkTextRef.SetTextParameters( m_timeRemaining, textParams );
		}
	}

	private const function ConvertFloatToTime( f : Float, out time : GameTime, out totalSeconds : Int32, out fraction : Int32 )
	{
		time = GameTime.MakeGameTime( 0, 0, 0, ( ( Int32 )( f ) ) );
		totalSeconds = GameTime.Minutes( time ) * 60;
		totalSeconds += GameTime.Seconds( time );
		fraction = ( ( Int32 )( ( f - ( ( Float )( FloorF( f ) ) ) ) * 100.0 ) );
		return;
	}

	private function FillIntroAnimationStart()
	{
		m_currentAnimProxy = PlayLibraryAnimation( 'FillIntroAnimation' );
		m_currentAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnFillIntroAnimationOver' );
	}

	protected event OnFillIntroAnimationOver( proxy : inkAnimProxy )
	{
		m_state = ECooldownIndicatorState.Filling;
		inkRectangleRef.SetSize( m_fill, m_fullSizeValue );
		proxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnFillIntroAnimationOver' );
	}

	private function FillOutroAnimationStart()
	{
		m_currentAnimProxy = PlayLibraryAnimation( 'FillOutroAnimation' );
		m_state = ECooldownIndicatorState.Outro;
		m_currentAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnFillOutroAnimationOver' );
	}

	protected event OnFillOutroAnimationOver( proxy : inkAnimProxy )
	{
		proxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnFillOutroAnimationOver' );
		HideCooldownWidget();
	}

	private function HideCooldownWidget()
	{
		GetRootWidget().SetVisible( false );
		m_state = ECooldownIndicatorState.Pooled;
	}

	public function GetState() : ECooldownIndicatorState
	{
		return m_state;
	}

	public function RemoveCooldown()
	{
		m_currentAnimProxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnFillIntroAnimationOver' );
		m_currentAnimProxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnFillOutroAnimationOver' );
		HideCooldownWidget();
	}

	public function IsIDMatch( id : TweakDBID ) : Bool
	{
		return m_buffData.buffID == id;
	}

}

