Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Windows.Forms
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASKanbanBoard

#Region "View state"

        Private Sub MoveSelectionToColumn(delta As Integer)
            Dim newColumn As Integer = MASKanbanBoardPolicy.ClampIndex(_selectedColumnIndex + delta, _columns.Count)
            If newColumn < 0 Then Return
            Dim newCard As Integer = -1
            If _columns(newColumn).Cards.Count > 0 Then newCard = Math.Min(Math.Max(0, _selectedCardIndex), _columns(newColumn).Cards.Count - 1)
            SetSelection(newColumn, newCard, True)
        End Sub

        Private Sub MoveSelectionWithinColumn(delta As Integer)
            If _selectedColumnIndex < 0 OrElse _selectedColumnIndex >= _columns.Count Then Return
            Dim column As KanbanColumnState = _columns(_selectedColumnIndex)
            If column.Cards.Count = 0 Then Return
            Dim current As Integer = If(_selectedCardIndex < 0, 0, _selectedCardIndex)
            SetSelection(_selectedColumnIndex, MASKanbanBoardPolicy.ClampIndex(current + delta, column.Cards.Count), True)
        End Sub

        Private Sub SetSelection(columnIndex As Integer,
                                 cardIndex As Integer,
                                 shouldRaiseEvent As Boolean)
            Dim previousColumn As Integer = _selectedColumnIndex
            Dim previousCard As Integer = _selectedCardIndex
            Dim normalizedColumn As Integer = MASKanbanBoardPolicy.ClampIndex(columnIndex, _columns.Count)
            Dim normalizedCard As Integer = -1
            If normalizedColumn >= 0 Then
                normalizedCard = MASKanbanBoardPolicy.ClampIndex(cardIndex, _columns(normalizedColumn).Cards.Count)
            End If
            Dim changed As Boolean = (_selectedColumnIndex <> normalizedColumn OrElse _selectedCardIndex <> normalizedCard)
            _selectedColumnIndex = normalizedColumn
            _selectedCardIndex = normalizedCard
            NormalizeSelection()
            If changed Then StartKanbanCardSelectionMotion(previousColumn, previousCard, _selectedColumnIndex, _selectedCardIndex)
            InvalidateVisual()
            If changed AndAlso shouldRaiseEvent Then RaiseSelectedCardChangedSafe()
        End Sub

        Private Sub NormalizeSelection()
            _selectedColumnIndex = MASKanbanBoardPolicy.ClampIndex(_selectedColumnIndex, _columns.Count)
            If _selectedColumnIndex >= 0 Then
                Dim column As KanbanColumnState = _columns(_selectedColumnIndex)
                _selectedCardIndex = MASKanbanBoardPolicy.ClampIndex(_selectedCardIndex, column.Cards.Count)
                If _lastLayoutPlan IsNot Nothing Then
                    column.TopCardIndex = _lastLayoutPlan.EnsureVisibleCardIndex(_selectedCardIndex, column.TopCardIndex, column.Cards.Count)
                Else
                    column.TopCardIndex = MASKanbanBoardPolicy.EnsureVisibleCardIndex(_selectedCardIndex, column.TopCardIndex, column.Cards.Count)
                End If
            Else
                _selectedCardIndex = -1
            End If
            If _lastLayoutPlan IsNot Nothing Then
                _leftColumnIndex = _lastLayoutPlan.EnsureVisibleColumnIndex(_selectedColumnIndex, _leftColumnIndex, _columns.Count)
            Else
                _leftColumnIndex = MASKanbanBoardPolicy.EnsureVisibleColumnIndex(_selectedColumnIndex, _leftColumnIndex, _columns.Count)
            End If
        End Sub

        Private Function GetSelectedColumn() As KanbanColumnState
            If _selectedColumnIndex < 0 OrElse _selectedColumnIndex >= _columns.Count Then Return Nothing
            Return _columns(_selectedColumnIndex)
        End Function

        Private Function GetSelectedCard() As KanbanCardState
            Dim column As KanbanColumnState = GetSelectedColumn()
            If column Is Nothing Then Return Nothing
            If _selectedCardIndex < 0 OrElse _selectedCardIndex >= column.Cards.Count Then Return Nothing
            Return column.Cards(_selectedCardIndex)
        End Function

        Private Function CanScrollColumnByWheel(columnIndex As Integer,
                                                delta As Integer) As Boolean
            If columnIndex < 0 OrElse columnIndex >= _columns.Count OrElse delta = 0 Then Return False
            Dim column As KanbanColumnState = _columns(columnIndex)
            Dim visibleCardCapacity As Integer = If(_lastLayoutPlan Is Nothing, KanbanBoardTokens.MaxVisibleCardsPerColumn, _lastLayoutPlan.MaxVisibleCardsPerColumn)
            If column Is Nothing OrElse column.Cards.Count <= visibleCardCapacity Then Return False
            Dim maxTop As Integer = If(_lastLayoutPlan Is Nothing, ResolveColumnMaxTop(column), Math.Max(0, column.Cards.Count - _lastLayoutPlan.MaxVisibleCardsPerColumn))
            If delta < 0 Then Return column.TopCardIndex < maxTop
            If delta > 0 Then Return column.TopCardIndex > 0
            Return False
        End Function

#End Region

    End Class

End Namespace
