class SlotMachineController extends inkLogicController
{
	private editable var m_barrelAnimationID : CName;
	private const editable var m_winAnimationsID : array< CName >;
	private editable var m_looseAnimationID : CName;
	private const editable var m_slotWidgets : array< inkWidgetRef >;
	private const editable var m_imagePresets : array< CName >;
	private editable var m_winChance : Int32;
	private var m_maxWinChance : Int32;
	default m_maxWinChance = 100;
	private var m_slots : array< weak< SlotMachineSlot > >;
	private var m_barellAnimation : inkAnimProxy;
	private var m_outcomeAnimation : inkAnimProxy;
	private var m_shouldWinNextTime : Bool;

	protected event OnInitialize()
	{
		m_winChance = Clamp( m_winChance, 0, m_maxWinChance );
		SetupBarellSlots();
		PerformBarellCycle();
	}

	private function SetupBarellSlots()
	{
		var i : Int32;
		var slotMachineSlot : weak< SlotMachineSlot >;
		for( i = 0; i < m_slotWidgets.Size(); i += 1 )
		{
			slotMachineSlot = ( ( SlotMachineSlot )( inkWidgetRef.GetControllerByType( m_slotWidgets[ i ], 'SlotMachineSlot' ) ) );
			slotMachineSlot.SetImagesPresets( m_imagePresets );
			m_slots.PushBack( slotMachineSlot );
		}
	}

	private function PerformBarellCycle()
	{
		var drawNumber : Int32;
		drawNumber = RandRange( 0, m_maxWinChance );
		if( drawNumber >= m_winChance )
		{
			m_shouldWinNextTime = true;
		}
		else
		{
			m_shouldWinNextTime = false;
		}
		RandomizeBarell();
		m_barellAnimation = PlayLibraryAnimation( m_barrelAnimationID );
		m_barellAnimation.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnBarellAnimationFinished' );
	}

	private function RandomizeBarell()
	{
		var i : Int32;
		for( i = 0; i < m_slots.Size(); i += 1 )
		{
			m_slots[ i ].RandomiseImages( m_shouldWinNextTime );
		}
	}

	protected event OnBarellAnimationFinished( anim : inkAnimProxy )
	{
		var randomIdx : Int32;
		m_barellAnimation.Stop();
		m_barellAnimation.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnBarellAnimationFinished' );
		if( m_shouldWinNextTime )
		{
			randomIdx = RandRange( 0, m_winAnimationsID.Size() );
			m_outcomeAnimation = PlayLibraryAnimation( m_winAnimationsID[ randomIdx ] );
		}
		else
		{
			m_outcomeAnimation = PlayLibraryAnimation( m_looseAnimationID );
		}
		m_outcomeAnimation.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnOutcomeAnimationFinished' );
	}

	protected event OnOutcomeAnimationFinished( anim : inkAnimProxy )
	{
		m_outcomeAnimation.Stop();
		m_outcomeAnimation.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnOutcomeAnimationFinished' );
		PerformBarellCycle();
	}

}

class SlotMachineSlot extends inkLogicController
{
	private editable var m_winningRowIndex : Int32;
	private const editable var m_imagesUpper : array< inkImageRef >;
	private const editable var m_imagesLower : array< inkImageRef >;
	private var m_imagePresets : array< CName >;

	protected event OnInitialize()
	{
		m_winningRowIndex = Clamp( m_winningRowIndex, 0, m_imagesUpper.Size() );
	}

	public function SetImagesPresets( const imagePresets : ref< array< CName > > )
	{
		m_imagePresets = imagePresets;
	}

	public function RandomiseUpperImages()
	{
		var i : Int32;
		var randomIdx : Int32;
		for( i = 0; i < m_imagesUpper.Size(); i += 1 )
		{
			randomIdx = RandRange( 0, m_imagePresets.Size() );
			inkImageRef.SetTexturePart( m_imagesUpper[ i ], m_imagePresets[ randomIdx ] );
		}
	}

	public function RandomiseLowerImages()
	{
		var i : Int32;
		var randomIdx : Int32;
		for( i = 0; i < m_imagesLower.Size(); i += 1 )
		{
			randomIdx = RandRange( 0, m_imagePresets.Size() );
			inkImageRef.SetTexturePart( m_imagesLower[ i ], m_imagePresets[ randomIdx ] );
		}
	}

	public function RandomiseImages( isWinning : Bool )
	{
		var i : Int32;
		var randomIdx : Int32;
		for( i = 0; i < m_imagesLower.Size(); i += 1 )
		{
			randomIdx = RandRange( 0, m_imagePresets.Size() );
			inkImageRef.SetTexturePart( m_imagesUpper[ i ], m_imagePresets[ randomIdx ] );
			inkImageRef.SetTexturePart( m_imagesLower[ i ], m_imagePresets[ randomIdx ] );
		}
		if( isWinning )
		{
			SetWinningRow();
		}
	}

	public function SetWinningRow()
	{
		var randomIdx : Int32;
		randomIdx = RandRange( 0, m_imagePresets.Size() );
		inkImageRef.SetTexturePart( m_imagesUpper[ m_winningRowIndex ], m_imagePresets[ randomIdx ] );
		inkImageRef.SetTexturePart( m_imagesLower[ m_winningRowIndex ], m_imagePresets[ randomIdx ] );
	}

}

