class NewPerksPerkContainerLogicController extends inkLogicController
{
	private editable var m_slotIdentifier : gamedataNewPerkSlotType;
	private editable var m_perkWidget : inkWidgetRef;
	private const editable var m_wiresConnections : array< NewPerksWireConnection >;

	protected event OnInitialize()
	{
		ClearLines();
	}

	public function GetSlotIdentifier() : gamedataNewPerkSlotType
	{
		return m_slotIdentifier;
	}

	public function GetPerkWidget() : inkWidgetRef
	{
		return m_perkWidget;
	}

	public function GetPerkWidgetController() : weak< NewPerksPerkItemLogicController >
	{
		return ( ( weak< weak< NewPerksPerkItemLogicController > > )( inkWidgetRef.GetController( m_perkWidget ) ) );
	}

	public function SetEnabled( value : Bool )
	{
		inkWidgetRef.SetVisible( m_perkWidget, value );
	}

	public function SetLinesState( perk : gamedataNewPerkSlotType )
	{
		SetLinesState( perk, NewPerksWireState.All );
	}

	public function SetLinesState( slot : gamedataNewPerkSlotType, state : NewPerksWireState )
	{
		var i, j, iLimit, jLimit : Int32;
		var styleState : CName;
		switch( state )
		{
			case NewPerksWireState.Default:
				styleState = 'Default';
			break;
			case NewPerksWireState.Available:
				styleState = 'Available';
			break;
			case NewPerksWireState.Bought:
				styleState = 'Bought';
			break;
		}
		for( i = 0, iLimit = m_wiresConnections.Size(); i < iLimit; i += 1 )
		{
			if( m_wiresConnections[ i ].m_targetSlot == slot || state == NewPerksWireState.All )
			{
				for( j = 0, jLimit = m_wiresConnections[ i ].m_wires.Size(); j < jLimit; j += 1 )
				{
					inkWidgetRef.SetState( m_wiresConnections[ i ].m_wires[ j ], styleState );
				}
			}
		}
	}

	public function ClearLines()
	{
		var i, j, iLimit, jLimit : Int32;
		for( i = 0, iLimit = m_wiresConnections.Size(); i < iLimit; i += 1 )
		{
			for( j = 0, jLimit = m_wiresConnections[ i ].m_wires.Size(); j < jLimit; j += 1 )
			{
				inkWidgetRef.SetVisible( m_wiresConnections[ i ].m_wires[ j ], false );
			}
		}
	}

	public function AddLine( lineTarget : gamedataNewPerkSlotType, perks : ref< array< weak< NewPerk_Record > > > )
	{
		var i, j, iLimit, jLimit : Int32;
		var dependanciesMet : Bool;
		for( i = 0, iLimit = m_wiresConnections.Size(); i < iLimit; i += 1 )
		{
			if( m_wiresConnections[ i ].m_targetSlot != lineTarget )
			{
				continue;
			}
			for( j = 0, jLimit = m_wiresConnections[ i ].m_wires.Size(); j < jLimit; j += 1 )
			{
				dependanciesMet = ConnectionDependanciesMet( m_wiresConnections[ i ], perks );
				inkWidgetRef.SetVisible( m_wiresConnections[ i ].m_wires[ j ], dependanciesMet );
			}
		}
	}

	private function ConnectionDependanciesMet( connection : ref< NewPerksWireConnection >, perks : ref< array< weak< NewPerk_Record > > > ) : Bool
	{
		var i : Int32;
		var result, dependancyPresent : Bool;
		var slotType : gamedataNewPerkSlotType;
		var perkRecord : weak< NewPerk_Record >;
		var requiredPerks : array< weak< NewPerk_Record > >;
		result = true;
		for( i = 0; i < connection.m_connectionDependancies.Size(); i += 1 )
		{
			slotType = connection.m_connectionDependancies[ i ];
			perkRecord = GetPerkBySlotType( slotType, perks );
			if( perkRecord == NULL )
			{
				result = result && !( connection.m_dependanciesPresenceToggle );
				continue;
			}
			perkRecord.RequiresPerks( requiredPerks );
			dependancyPresent = requiredPerks.Contains( GetPerkWidgetController().GetPerkRecord() );
			result = result && dependancyPresent == connection.m_dependanciesPresenceToggle;
		}
		return result;
	}

	private function GetPerkBySlotType( slotType : gamedataNewPerkSlotType, perks : ref< array< weak< NewPerk_Record > > > ) : weak< NewPerk_Record >
	{
		var i : Int32;
		for( i = 0; i < perks.Size(); i += 1 )
		{
			if( perks[ i ].Slot().Type() == slotType )
			{
				return perks[ i ];
			}
		}
		return NULL;
	}

	public function GetWires( target : gamedataNewPerkSlotType ) : array< inkWidgetRef >
	{
		var i, limit : Int32;
		var emptyResult : array< inkWidgetRef >;
		for( i = 0, limit = m_wiresConnections.Size(); i < limit; i += 1 )
		{
			if( m_wiresConnections[ i ].m_targetSlot == target )
			{
				if( AreConnectionWiresVisible( m_wiresConnections[ i ] ) )
				{
					return m_wiresConnections[ i ].m_wires;
				}
			}
		}
		return emptyResult;
	}

	public function GetWiresWithTargetBlacklist( targetBlacklist : ref< array< gamedataNewPerkSlotType > > ) : array< inkWidgetRef >
	{
		var i, j : Int32;
		var resultArray : array< inkWidgetRef >;
		for( i = 0; i < m_wiresConnections.Size(); i += 1 )
		{
			if( AreConnectionWiresVisible( m_wiresConnections[ i ] ) )
			{
				if( !( targetBlacklist.Contains( m_wiresConnections[ i ].m_targetSlot ) ) )
				{
					for( j = 0; j < m_wiresConnections[ i ].m_wires.Size(); j += 1 )
					{
						resultArray.PushBack( m_wiresConnections[ i ].m_wires[ j ] );
					}
				}
			}
		}
		return resultArray;
	}

	public function AreAnyWiresActive() : Bool
	{
		var i, j : Int32;
		var widget : inkWidgetRef;
		for( i = 0; i < m_wiresConnections.Size(); i += 1 )
		{
			for( j = 0; j < m_wiresConnections[ i ].m_wires.Size(); j += 1 )
			{
				widget = m_wiresConnections[ i ].m_wires[ j ];
				if( inkWidgetRef.IsVisible( widget ) && inkWidgetRef.GetState( widget ) == 'Bought' )
				{
					return true;
				}
			}
		}
		return false;
	}

	private function AreConnectionWiresVisible( connection : ref< NewPerksWireConnection > ) : Bool
	{
		return ( connection.m_wires.Size() > 0 ) && inkWidgetRef.IsVisible( connection.m_wires[ 0 ] );
	}

}

struct NewPerksWireConnection
{
	editable var m_targetSlot : gamedataNewPerkSlotType;
	[ tooltip = "true - wires visible if all dependancies are present and connected; false - wires visible if all dependancies are not present or disconnected" ]
	editable var m_dependanciesPresenceToggle : Bool;
	[ tooltip = "list of slots that need to be active and connected or inactive/disconnected for wires to be shown" ]
	const editable var m_connectionDependancies : array< gamedataNewPerkSlotType >;
	const editable var m_wires : array< inkWidgetRef >;
}

enum NewPerksWireState
{
	Default = 0,
	Available = 1,
	Bought = 2,
	Count = 3,
	All = 4,
	Invalid = -1,
}

