Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Components

    Partial Friend NotInheritable Class MASDatePickerCalendarView

#Region "Input"

        Protected Overrides Sub OnMouseMove(ctx As MASThemeContext, ptPx As SKPoint)
            Dim hit As HitTarget = HitTestTarget(ptPx)
            If SameHit(_hoverTarget, hit) Then Return

            _hoverTarget = hit
            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

            RequestFocus()
            _pressedTarget = HitTestTarget(ptPx)
            InvalidateVisual()
            Return (_pressedTarget.Part <> HitPart.None)
        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 pressed As HitTarget = _pressedTarget
            _pressedTarget = New HitTarget()
            Dim released As HitTarget = HitTestTarget(ptPx)

            If SameHit(pressed, released) Then
                Select Case released.Part
                    Case HitPart.PreviousMonth
                        If _calendarMode = CalendarMode.MonthYear Then
                            MoveYearWindow(-MonthYearWindowPageSizeYears)
                        Else
                            MoveMonth(-1)
                        End If

                    Case HitPart.NextMonth
                        If _calendarMode = CalendarMode.MonthYear Then
                            MoveYearWindow(MonthYearWindowPageSizeYears)
                        Else
                            MoveMonth(1)
                        End If

                    Case HitPart.MonthYearTitle
                        ToggleMonthYearSelector()

                    Case HitPart.MonthChip
                        If released.Index >= 0 AndAlso released.Index < _lastMonthValues.Length Then
                            Dim monthValue As Integer = Math.Max(1, Math.Min(12, _lastMonthValues(released.Index)))
                            ApplyMonthYear(_displayMonth.Year, monthValue)
                        End If

                    Case HitPart.YearChip
                        If released.Index >= 0 AndAlso released.Index < _lastYearValues.Length Then
                            ApplyMonthYear(_lastYearValues(released.Index), _pendingMonth)
                        End If

                    Case HitPart.DayCell
                        If IsDateAllowed(released.Value) Then
                            Dim previousDate As Nullable(Of Date) = _selectedDate
                            _selectedDate = released.Value.Date
                            StartCalendarSelectionMotion(previousDate, _selectedDate)
                            _onDateSelected?.Invoke(released.Value.Date)
                        End If
                End Select
            End If

            InvalidateVisual()
            Return pressed.Part <> HitPart.None
        End Function

        Protected Overrides Sub OnMouseLeave(ctx As MASThemeContext)
            _hoverTarget = New HitTarget()
            _pressedTarget = New HitTarget()
            InvalidateVisual()
        End Sub

        Protected Overrides Sub OnMouseCancel(ctx As MASThemeContext)
            _hoverTarget = New HitTarget()
            _pressedTarget = New HitTarget()
            InvalidateVisual()
        End Sub

        Protected Overrides Function OnKeyDown(ctx As MASThemeContext,
                                               keyCode As Keys) As Boolean
            Select Case keyCode
                Case Keys.Left
                    MoveKeyboardDate(-1)
                    Return True

                Case Keys.Right
                    MoveKeyboardDate(1)
                    Return True

                Case Keys.Up
                    MoveKeyboardDate(-7)
                    Return True

                Case Keys.Down
                    MoveKeyboardDate(7)
                    Return True

                Case Keys.PageUp
                    If _calendarMode = CalendarMode.MonthYear Then
                        MoveYearWindow(-MonthYearWindowPageSizeYears)
                    Else
                        MoveMonth(-1)
                    End If
                    Return True

                Case Keys.PageDown
                    If _calendarMode = CalendarMode.MonthYear Then
                        MoveYearWindow(MonthYearWindowPageSizeYears)
                    Else
                        MoveMonth(1)
                    End If
                    Return True

                Case Keys.Home
                    MoveKeyboardTo(New Date(_displayMonth.Year, _displayMonth.Month, 1))
                    Return True

                Case Keys.End
                    MoveKeyboardTo(New Date(_displayMonth.Year, _displayMonth.Month, DateTime.DaysInMonth(_displayMonth.Year, _displayMonth.Month)))
                    Return True

                Case Keys.Enter, Keys.Space
                    If _calendarMode = CalendarMode.MonthYear Then
                        ToggleMonthYearSelector()
                    Else
                        Dim d As Date = ResolveKeyboardDate()
                        If IsDateAllowed(d) Then
                            Dim previousDate As Nullable(Of Date) = _selectedDate
                            _selectedDate = d.Date
                            StartCalendarSelectionMotion(previousDate, _selectedDate)
                            _onDateSelected?.Invoke(d.Date)
                        End If
                    End If
                    Return True

                Case Keys.Escape
                    If _calendarMode = CalendarMode.MonthYear Then
                        _calendarMode = CalendarMode.Days
                        InvalidateVisual()
                        Return True
                    End If
            End Select

            Return False
        End Function

        Protected Overrides Function WantsKeyboardFocus() As Boolean
            Return True
        End Function

#End Region

    End Class

End Namespace
