struct CellData
{
	var position : Vector2;
	var element : ElementData;
	var properties : SpecialProperties;
	var assignedCell : weak< NetworkMinigameGridCellController >;
	var consumed : Bool;
}

struct SpecialProperties
{
	var enemyMarker : Bool;
	var traps : array< ETrap >;
}

enum ETrap
{
	Invalid = 0,
	GridRegen = 1,
	AppendStart = 2,
	Hidden = 3,
	Virus = 4,
}

class NetworkMinigameGridController extends inkLogicController
{
	protected editable var m_gridContainer : inkWidgetRef;
	protected editable var m_horizontalHoverHighlight : inkWidgetRef;
	protected editable var m_horizontalCurrentHighlight : inkWidgetRef;
	protected editable var m_verticalHoverHighlight : inkWidgetRef;
	protected editable var m_verticalCurrentHighlight : inkWidgetRef;
	protected editable var m_gridVisualOffset : Vector2;
	protected editable var m_gridCellLibraryName : CName;
	var m_gridData : array< CellData >;
	var m_lastSelected : CellData;
	var m_currentActivePosition : Vector2;
	var m_isHorizontalHighlight : Bool;
	var m_lastHighlighted : CellData;
	private var m_animProxy : inkAnimProxy;
	private var m_animHighlightProxy : inkAnimProxy;
	private var m_firstBoot : Bool;
	private var m_isHorizontal : Bool;

	protected event OnInitialize()
	{
		inkWidgetRef.SetTranslation( m_gridContainer, m_gridVisualOffset );
		m_firstBoot = true;
	}

	private function Clear()
	{
		var toClear : inkCompoundWidget;
		toClear = ( ( inkCompoundWidget )( inkWidgetRef.Get( m_gridContainer ) ) );
		toClear.RemoveAllChildren();
	}

	public function SetUp( const gridData : ref< array< CellData > > )
	{
		SetGridData( gridData );
		m_isHorizontalHighlight = true;
		m_lastSelected = FindCellData( Vector2( 0.0, 0.0 ) );
		m_lastSelected.assignedCell.Consume();
		HighlightCellSet( 0, false, true );
	}

	public function SetGridData( const gridData : ref< array< CellData > > )
	{
		var i : Int32;
		Clear();
		m_gridData = gridData;
		for( i = 0; i < m_gridData.Size(); i += 1 )
		{
			m_gridData[ i ].assignedCell = ( ( NetworkMinigameGridCellController )( AddCell( gridData[ i ] ).GetController() ) );
		}
	}

	private function AddCell( const toAdd : ref< CellData > ) : weak< inkWidget >
	{
		var cellLogic : weak< NetworkMinigameGridCellController >;
		var cell : weak< inkWidget >;
		cell = SpawnFromLocal( inkWidgetRef.Get( m_gridContainer ), m_gridCellLibraryName );
		cellLogic = ( ( NetworkMinigameGridCellController )( cell.GetController() ) );
		cellLogic.Spawn( toAdd, this );
		return cell;
	}

	public function SetCurrentActivePosition( position : Vector2, isHorizontal : Bool )
	{
		m_currentActivePosition = position;
		m_isHorizontalHighlight = isHorizontal;
		HighlightCellSet( ( ( Int32 )( ( ( m_isHorizontalHighlight ) ? ( position.X ) : ( position.Y ) ) ) ), false, m_isHorizontalHighlight );
	}

	public function SetLastCellSelected( const cell : ref< CellData > )
	{
		if( !( cell.assignedCell.IsConsumed() ) )
		{
			m_lastSelected = cell;
			CallCustomCallback( 'OnCellSelected' );
		}
	}

	public function GetLastCellSelected() : CellData
	{
		return m_lastSelected;
	}

	public function GetGrid() : array< CellData >
	{
		return m_gridData;
	}

	public function FindCellData( position : Vector2 ) : CellData
	{
		var i : Int32;
		var result : CellData;
		for( i = 0; i < m_gridData.Size(); i += 1 )
		{
			if( ( m_gridData[ i ].position.X == position.X ) && ( m_gridData[ i ].position.Y == position.Y ) )
			{
				result = m_gridData[ i ];
				return result;
			}
		}
		return result;
	}

	public function HighlightFromCellHover( position : Vector2 )
	{
		if( IsOnCurrentCellSet( position ) )
		{
			HighlightCellSet( ( ( Int32 )( ( ( m_isHorizontalHighlight ) ? ( position.Y ) : ( position.X ) ) ) ), true, !( m_isHorizontalHighlight ) );
		}
	}

	public function IsOnCurrentCellSet( position : Vector2 ) : Bool
	{
		return ( ( m_isHorizontalHighlight ) ? ( position.X ) : ( position.Y ) ) == ( ( m_isHorizontalHighlight ) ? ( m_lastSelected.position.X ) : ( m_lastSelected.position.Y ) );
	}

	public function RemoveHighlightFromCellHover()
	{
		if( m_lastHighlighted.assignedCell )
		{
			m_lastHighlighted.assignedCell.SetHighlightStatus( false );
		}
	}

	private function HighlightCellSet( index : Int32, isHover : Bool, isHorizontal : Bool )
	{
		var highlightToMove : inkWidgetRef;
		var cellSize : Vector2;
		var cellToHighlightPos : Vector2;
		var cellWidget : weak< inkWidget >;
		var newHorizontalPivot : Vector2;
		var newVerticalPivor : Vector2;
		var fullScale : Vector2;
		if( m_gridData.Size() == 0 )
		{
			return;
		}
		cellWidget = m_gridData[ 0 ].assignedCell.GetRootWidget();
		cellSize = cellWidget.GetSize();
		m_isHorizontal = isHorizontal;
		if( isHorizontal )
		{
			highlightToMove = ( ( isHover ) ? ( m_horizontalHoverHighlight ) : ( m_horizontalCurrentHighlight ) );
			inkWidgetRef.SetTranslation( highlightToMove, 0.0, ( ( ( Float )( index ) ) * cellSize.Y ) + m_gridVisualOffset.Y );
			cellToHighlightPos = Vector2( ( ( Float )( index ) ), m_lastSelected.position.Y );
		}
		else
		{
			highlightToMove = ( ( isHover ) ? ( m_verticalHoverHighlight ) : ( m_verticalCurrentHighlight ) );
			inkWidgetRef.SetTranslation( highlightToMove, ( ( ( Float )( index ) ) * cellSize.X ) + m_gridVisualOffset.Y, 0.0 );
			cellToHighlightPos = Vector2( m_lastSelected.position.X, ( ( Float )( index ) ) );
		}
		if( !( isHover ) )
		{
			if( m_lastHighlighted.assignedCell )
			{
				m_lastHighlighted.assignedCell.SetHighlightStatus( false );
			}
		}
		else
		{
			m_lastHighlighted = FindCellData( cellToHighlightPos );
			m_lastHighlighted.assignedCell.SetHighlightStatus( true );
		}
		inkWidgetRef.SetSize( highlightToMove, cellSize );
		RefreshDimLevels( index, isHorizontal );
		if( !( isHover ) && !( m_firstBoot ) )
		{
			newHorizontalPivot.X = ( ( Float )( ( ( 650 / 5 ) * index ) / 650 ) );
			newVerticalPivor.Y = ( ( Float )( ( ( 400 / 5 ) * index ) / 400 ) );
			inkWidgetRef.SetRenderTransformPivot( m_horizontalHoverHighlight, newHorizontalPivot );
			inkWidgetRef.SetRenderTransformPivot( m_verticalHoverHighlight, newVerticalPivor );
			m_animProxy.Stop();
			if( isHorizontal )
			{
				m_animProxy = PlayLibraryAnimation( 'AnimationVerticalToHorizontal' );
			}
			else
			{
				m_animProxy = PlayLibraryAnimation( 'AnimationHorizontalToVertical' );
			}
		}
		if( isHover && !( m_firstBoot ) )
		{
			if( m_animHighlightProxy && m_animHighlightProxy.IsPlaying() )
			{
				m_animHighlightProxy.Stop();
			}
			fullScale.X = 1.0;
			fullScale.Y = 1.0;
			m_animHighlightProxy.Stop();
			if( isHorizontal )
			{
				m_animHighlightProxy = PlayLibraryAnimation( 'horizonal_highlight' );
				inkWidgetRef.SetSize( m_horizontalCurrentHighlight, cellSize );
				inkWidgetRef.SetScale( m_horizontalCurrentHighlight, fullScale );
				inkWidgetRef.SetTranslation( m_horizontalCurrentHighlight, 0.0, ( ( ( Float )( index ) ) * cellSize.Y ) + m_gridVisualOffset.Y );
			}
			else
			{
				m_animHighlightProxy = PlayLibraryAnimation( 'vertical_highlight' );
				inkWidgetRef.SetSize( m_verticalCurrentHighlight, cellSize );
				inkWidgetRef.SetScale( m_verticalCurrentHighlight, fullScale );
				inkWidgetRef.SetTranslation( m_verticalCurrentHighlight, ( ( ( Float )( index ) ) * cellSize.X ) + m_gridVisualOffset.Y, 0.0 );
			}
		}
		m_firstBoot = false;
	}

	public function RefreshDimLevels( index : Int32, isHorizontal : Bool )
	{
		var i : Int32;
		for( i = 0; i < m_gridData.Size(); i += 1 )
		{
			m_gridData[ i ].assignedCell.SetElementActive( !( IsOnCurrentCellSet( m_gridData[ i ].position ) ) );
		}
	}

}

class NetworkMinigameGridCellController extends inkButtonController
{
	var m_cellData : CellData;
	private var m_grid : weak< NetworkMinigameGridController >;
	protected editable var m_slotsContainer : inkWidgetRef;
	protected var m_slotsContent : weak< NetworkMinigameElementController >;
	protected editable var m_elementLibraryName : CName;
	private var m_defaultColor : HDRColor;

	protected event OnInitialize()
	{
		inkWidgetRef.RegisterToCallback( m_slotsContainer, 'OnRelease', this, 'OnReleaseContainer' );
	}

	public function Spawn( const setUp : ref< CellData >, grid : weak< NetworkMinigameGridController > )
	{
		var slot : weak< inkWidget >;
		m_cellData = setUp;
		m_grid = grid;
		slot = SpawnFromLocal( inkWidgetRef.Get( m_slotsContainer ), m_elementLibraryName );
		m_slotsContent = ( ( NetworkMinigameElementController )( slot.GetController() ) );
		m_slotsContent.SetContent( setUp.element );
		if( m_cellData.consumed )
		{
			m_slotsContent.Consume();
		}
		m_defaultColor = slot.GetTintColor();
	}

	protected event OnButtonStateChanged( controller : weak< inkButtonController >, oldState : inkEButtonState, newState : inkEButtonState )
	{
		switch( newState )
		{
			case inkEButtonState.Normal:
				m_grid.RemoveHighlightFromCellHover();
			break;
			case inkEButtonState.Hover:
				m_grid.HighlightFromCellHover( m_cellData.position );
			break;
			case inkEButtonState.Press:
				PlaySound( 'Button', 'OnPress' );
			break;
			case inkEButtonState.Disabled:
				break;
		}
	}

	public function SetHighlightStatus( isHighlighted : Bool )
	{
		m_slotsContent.SetHighlightStatus( isHighlighted && !( m_cellData.consumed ) );
	}

	protected event OnReleaseContainer( e : inkPointerEvent )
	{
		if( !( m_cellData.consumed ) )
		{
			m_grid.SetLastCellSelected( m_cellData );
			m_grid.RemoveHighlightFromCellHover();
		}
	}

	public function Consume()
	{
		m_cellData.consumed = true;
		m_slotsContent.Consume();
	}

	public function IsConsumed() : Bool
	{
		return m_cellData.consumed;
	}

	public function SetElementActive( isDimmed : Bool )
	{
		var root : weak< inkWidget >;
		m_slotsContent.SetElementActive( isDimmed );
		root = GetRootWidget();
		root.SetInteractive( !( isDimmed ) );
	}

}

