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 MASTreeGrid

#Region "Input"

        Protected Overrides Sub OnMouseMove(ctx As MASThemeContext, ptPx As SKPoint)
            Dim hit As TreeGridRowHit = HitTestRow(ptPx)
            Dim key As String = If(hit IsNot Nothing, hit.RowKey, String.Empty)
            If String.Equals(_hoverRowKey, key, StringComparison.Ordinal) Then Return
            _hoverRowKey = key
            InvalidateVisual()
        End Sub

        Protected Overrides Function OnMouseDown(ctx As MASThemeContext,
                                                 ptPx As SKPoint,
                                                 button As Integer) As Boolean
            If button <> CInt(MouseButtons.Left) Then Return False
            Dim hit As TreeGridRowHit = HitTestRow(ptPx)
            If hit IsNot Nothing Then
                _pressedRowKey = hit.RowKey
                InvalidateVisual()
                Return True
            End If
            Return _contentRect.Contains(ptPx.X, ptPx.Y)
        End Function

        Protected Overrides Function OnMouseUp(ctx As MASThemeContext,
                                               ptPx As SKPoint,
                                               button As Integer) As Boolean
            If button <> CInt(MouseButtons.Left) Then Return False
            Dim pressedKey As String = _pressedRowKey
            _pressedRowKey = String.Empty
            Dim hit As TreeGridRowHit = HitTestRow(ptPx)
            If hit IsNot Nothing AndAlso String.Equals(hit.RowKey, pressedKey, StringComparison.Ordinal) Then
                If hit.ExpanderRect.Contains(ptPx.X, ptPx.Y) AndAlso ToggleRow(hit.RowKey) Then Return True
                SetSelection(hit.RowKey, True)
                Return True
            End If
            If pressedKey.Length > 0 Then
                InvalidateVisual()
                Return True
            End If
            Return False
        End Function

        Protected Overrides Sub OnMouseLeave(ctx As MASThemeContext)
            ResetPointerState()
        End Sub

        Protected Overrides Sub OnMouseCancel(ctx As MASThemeContext)
            ResetPointerState()
        End Sub

        Protected Overrides Sub OnHostLostFocus(ctx As MASThemeContext)
            _pressedRowKey = String.Empty
            InvalidateVisual()
        End Sub

        Friend Overrides Function WantsPointerWheel(ctx As MASThemeContext,
                                                      ptPx As SKPoint) As Boolean
            Return Visible AndAlso Enabled AndAlso
                   _gridRect.Contains(ptPx.X, ptPx.Y) AndAlso
                   HasScrollableRowViewport()
        End Function

        Friend Overrides Function CanHandlePointerWheel(ctx As MASThemeContext,
                                                        delta As Integer,
                                                        ptPx As SKPoint) As Boolean
            If delta = 0 OrElse Not WantsPointerWheel(ctx, ptPx) Then Return False
            Return CanScrollRowViewport(delta)
        End Function

        Protected Overrides Sub OnMouseWheel(ctx As MASThemeContext,
                                             delta As Integer,
                                             ptPx As SKPoint)
            If Not CanScrollRowViewport(delta) Then Return
            If delta < 0 Then
                ScrollRows(1)
            ElseIf delta > 0 Then
                ScrollRows(-1)
            End If
        End Sub

        Protected Overrides Function OnKeyDown(ctx As MASThemeContext,
                                               keyCode As Keys) As Boolean
            If Not Enabled Then Return False

            If IsEditingRow Then
                Select Case keyCode
                    Case Keys.Enter, Keys.Return
                        Return CommitEdit()
                    Case Keys.Escape
                        Return CancelEdit()
                End Select
            End If

            If RowCount = 0 Then Return False
            Dim visible As List(Of VisibleTreeGridRow) = BuildVisibleRows()
            If visible.Count = 0 Then Return False
            Dim selectedIndex As Integer = FindVisibleIndex(_selectedRowKey, visible)
            If selectedIndex < 0 Then selectedIndex = 0

            Select Case keyCode
                Case Keys.F2
                    Return BeginEditSelectedLabel()
                Case Keys.Enter, Keys.Return
                    Return BeginEditSelectedLabel()
                Case Keys.Up
                    SelectVisibleIndex(Math.Max(0, selectedIndex - 1), visible)
                    Return True
                Case Keys.Down
                    SelectVisibleIndex(Math.Min(visible.Count - 1, selectedIndex + 1), visible)
                    Return True
                Case Keys.Home
                    SelectVisibleIndex(0, visible)
                    Return True
                Case Keys.End
                    SelectVisibleIndex(visible.Count - 1, visible)
                    Return True
                Case Keys.Left
                    If CollapseOrMoveToParent(visible(selectedIndex).Row, MASTreeGridPolicy.ResolveRightToLeft()) Then Return True
                Case Keys.Right
                    If ExpandOrMoveToChild(visible(selectedIndex).Row, MASTreeGridPolicy.ResolveRightToLeft()) Then Return True
            End Select
            Return False
        End Function

        Protected Overrides Function WantsKeyboardFocus() As Boolean
            Return MASCompositeContentFocusPolicy.CanReceiveKeyboardFocus(Me.ArchitectureContract, Visible, Enabled)
        End Function

        Protected Overrides Function WantsPointerFocus() As Boolean
            Return MASCompositeContentFocusPolicy.AllowsPointerFocusForCompositeContent(Me.ArchitectureContract, Visible, Enabled)
        End Function

#End Region

    End Class

End Namespace
