class RadialStatusEffectController extends inkLogicController
{
	private editable var effectsContainerRef : inkCompoundRef;
	private editable var poolHolderRef : inkCompoundRef;
	private editable var effectTemplateRef : inkWidgetLibraryReference;
	private editable var maxSize : Int32;
	default maxSize = 8;
	private var effects : array< weak< SingleCooldownManager > >;

	protected event OnInitialize()
	{
		var i : Int32;
		var effect : SingleCooldownManager;
		for( i = 0; i < maxSize; i += 1 )
		{
			effect = ( ( SingleCooldownManager )( SpawnFromLocal( inkCompoundRef.Get( poolHolderRef ), effectTemplateRef.widgetItem ).GetController() ) );
			effect.Init( poolHolderRef, effectsContainerRef );
			effects.PushBack( effect );
		}
	}

}

class PointerController extends inkLogicController
{
	private const editable var m_connectors : array< inkWidgetRef >;
	private editable var m_pointer : inkWidgetRef;
	private editable var m_centerButtonSlot : inkWidgetRef;
	private editable var m_centerButton : weak< inkWidget >;
	private var currentIndex : Int32;
	default currentIndex = -1;

	protected event OnInitialize()
	{
		var i : Int32;
		var inputKey : inkInputKeyData;
		for( i = 0; i < m_connectors.Size(); i += 1 )
		{
			inkWidgetRef.Get( m_connectors[ i ] ).SetVisible( false );
		}
		inkWidgetRef.Get( m_pointer ).SetVisible( false );
		if( m_centerButton )
		{
			inkInputKeyData.SetInputKey( inputKey, EInputKey.IK_Pad_RightThumb );
			( ( inkInputDisplayController )( m_centerButton.GetController() ) ).SetInputKey( inputKey );
			m_centerButton.SetAnchor( inkEAnchor.Centered );
			m_centerButton.SetAnchorPoint( Vector2( 0.5, 0.5 ) );
			m_centerButton.SetVisible( false );
		}
	}

	public function Enable()
	{
		inkWidgetRef.Get( m_pointer ).SetVisible( true );
	}

	public function UpdateCenterPiece( rawInputAngle : Vector4 ) {}

	public function SetRotation( rawInputAngle : Vector4, angle : Float, activeIndex : Int32 )
	{
		inkWidgetRef.Get( m_pointer ).SetRotation( angle + 45.0 );
		if( activeIndex == currentIndex )
		{
			return;
		}
		if( ( currentIndex != -1 ) && inkWidgetRef.Get( m_connectors[ currentIndex ] ) )
		{
			inkWidgetRef.Get( m_connectors[ currentIndex ] ).SetVisible( false );
		}
		if( ( activeIndex != -1 ) && inkWidgetRef.Get( m_connectors[ activeIndex ] ) )
		{
			inkWidgetRef.Get( m_connectors[ activeIndex ] ).SetVisible( true );
		}
		currentIndex = activeIndex;
	}

}

class PointerSlot extends RadialSlot
{

	public const function GetController() : PointerController
	{
		return ( ( PointerController )( GetWidget().GetController() ) );
	}

}

class StatusEffectSlot extends RadialSlot
{

	public const function GetController() : RadialStatusEffectController
	{
		return ( ( RadialStatusEffectController )( GetWidget().GetController() ) );
	}

}

class WeaponRadialSlot extends RadialSlot
{
	private editable var equipmentArea : gamedataEquipmentArea;
	private var index : Int32;

	public const function GetController() : InventoryItemDisplayController
	{
		return ( ( InventoryItemDisplayController )( GetWidget().GetController() ) );
	}

	public const function GetEquipmentArea() : gamedataEquipmentArea
	{
		return equipmentArea;
	}

	public const function GetIndex() : Int32
	{
		return index;
	}

	public function SetIndex( i : Int32 )
	{
		index = i;
	}

	public const override function GetDebugInfo( out info : array< String > )
	{
		super.GetDebugInfo( info );
		info.PushBack( "Index: " + IntToString( index ) );
		info.PushBack( "Area: " + EnumValueToString( "gamedataEquipmentArea", ( ( Int32 )( equipmentArea ) ) ) );
		info.PushBack( "-" * 32 );
	}

}

struct RadialAnimData
{
	editable var hover_in : CName;
	default hover_in = 'Anim name for hover in';
	editable var hover_out : CName;
	default hover_out = 'Anim name for hover out';
	editable var cycle_in : CName;
	default cycle_in = 'Anim name for cycle in animation';
	editable var cycle_out : CName;
	default cycle_out = 'Anim name for cycle out animation';
}

class RadialSlot extends IScriptable
{
	[ tooltip = "Achnor at which provided library reference should be spawned into" ]
	editable var slotAnchorRef : inkWidgetRef;
	[ tooltip = "Specify library item that you want to be spawned in this slot" ]
	editable var libraryRef : inkWidgetLibraryReference;
	editable var slotType : SlotType;
	protected editable var animData : RadialAnimData;
	private var widget : weak< inkWidget >;
	private var targetAngle : Float;
	private var active : String;
	default active = "Hover";
	private var inactive : String;
	default inactive = "Default";
	private var blocked : String;
	default blocked = "Blocked";

	public function Construct( w : weak< inkWidget > )
	{
		widget = w;
	}

	public const function GetWidget() : weak< inkWidget >
	{
		return widget;
	}

	public const virtual function IsCyclable() : Bool
	{
		return false;
	}

	public const virtual function CanCycle() : Bool
	{
		return false;
	}

	public const function GetAngle() : Float
	{
		return targetAngle;
	}

	public const virtual function GetDebugInfo( out info : array< String > )
	{
		info.PushBack( EnumValueToString( "SlotType", ( ( Int32 )( slotType ) ) ) );
		info.PushBack( FloatToString( targetAngle ) );
		info.PushBack( "-" * 32 );
	}

	public function Activate()
	{
		inkWidgetRef.Get( slotAnchorRef ).SetState( StringToName( active ) );
		Activate( true );
	}

	public function Deactivate()
	{
		inkWidgetRef.Get( slotAnchorRef ).SetState( StringToName( inactive ) );
		Activate( false );
	}

	public function SetTargetAngle( precalculatedAngle : Float )
	{
		targetAngle = precalculatedAngle;
	}

	protected virtual function Activate( shouldActivate : Bool )
	{
		var controller : inkLogicController;
		controller = GetWidget().GetController();
		if( !( controller ) )
		{
			return;
		}
		if( shouldActivate )
		{
			controller.PlayLibraryAnimation( animData.hover_in );
			controller.PlaySound( 'Button', 'OnHover' );
		}
		else
		{
			controller.PlayLibraryAnimation( animData.hover_out );
		}
	}

}

class CyclableRadialSlot extends WeaponRadialSlot
{
	editable var leftArrowEmpty : inkWidgetRef;
	editable var leftArrowFull : inkWidgetRef;
	editable var rightArrowEmpty : inkWidgetRef;
	editable var rightArrowFull : inkWidgetRef;
	private var canCycle : Bool;
	var isCycling : Bool;
	private var wasCyclingRight : Bool;
	private editable var hotkey : EHotkey;

	public const override function IsCyclable() : Bool
	{
		return true;
	}

	public const override function CanCycle() : Bool
	{
		return canCycle;
	}

	public const function GetHotkey() : EHotkey
	{
		return hotkey;
	}

	public const override function GetDebugInfo( out info : array< String > )
	{
		super.GetDebugInfo( info );
		info.PushBack( "HOTKEY: " + EnumValueToString( "EHotkey", ( ( Int32 )( hotkey ) ) ) );
		info.PushBack( "Can Cycle: " + BoolToString( canCycle ) );
	}

	public function SetCanCycle( _canCycle : Bool )
	{
		canCycle = _canCycle;
		inkWidgetRef.Get( leftArrowEmpty ).SetVisible( canCycle );
		inkWidgetRef.Get( rightArrowEmpty ).SetVisible( canCycle );
		if( !( canCycle ) )
		{
			CycleStop();
		}
	}

	public function CycleStart( right : Bool )
	{
		isCycling = true;
		if( right )
		{
			inkWidgetRef.Get( rightArrowFull ).SetVisible( true );
			wasCyclingRight = true;
		}
		else
		{
			inkWidgetRef.Get( leftArrowFull ).SetVisible( true );
			wasCyclingRight = false;
		}
	}

	public function CycleStop()
	{
		isCycling = false;
		if( wasCyclingRight )
		{
			inkWidgetRef.Get( rightArrowFull ).SetVisible( false );
		}
		else
		{
			inkWidgetRef.Get( leftArrowFull ).SetVisible( false );
		}
	}

	protected override function Activate( shouldActivate : Bool )
	{
		var showArrows : Bool;
		showArrows = shouldActivate && canCycle;
		inkWidgetRef.Get( leftArrowEmpty ).SetVisible( showArrows );
		inkWidgetRef.Get( rightArrowEmpty ).SetVisible( showArrows );
		if( !( shouldActivate ) )
		{
			CycleStop();
		}
		super.Activate( shouldActivate );
	}

}

