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 MASAgendaView

#Region "View State"

        Private Sub MoveSelection(delta As Integer)
            If _events.Count = 0 Then Return
            Dim visible As List(Of Integer) = GetVisibleEventIndicesForCurrentView()
            If visible.Count = 0 Then Return
            Dim visiblePosition As Integer = visible.IndexOf(_selectedEventIndex)
            If visiblePosition < 0 Then visiblePosition = If(delta < 0, visible.Count, -1)
            visiblePosition = Math.Max(0, Math.Min(visible.Count - 1, visiblePosition + delta))
            SetSelection(visible(visiblePosition), True)
        End Sub

        Private Sub SetSelection(index As Integer,
                                 shouldRaiseEvent As Boolean)
            Dim normalized As Integer = MASAgendaViewPolicy.ClampIndex(index, _events.Count)
            If index < 0 Then normalized = -1
            If _selectedEventIndex = normalized Then Return
            Dim previousIndex As Integer = _selectedEventIndex
            _selectedEventIndex = normalized
            _topEventIndex = MASAgendaViewPolicy.EnsureVisibleEventIndex(_selectedEventIndex, _topEventIndex, _events.Count)
            StartAgendaEventSelectionMotion(previousIndex, _selectedEventIndex)
            InvalidateVisual()
            If shouldRaiseEvent Then RaiseSelectedEventChangedSafe()
        End Sub

        Private Sub NormalizeEventOrderAndSelection()
            Dim selectedKey As String = String.Empty
            If _selectedEventIndex >= 0 AndAlso _selectedEventIndex < _events.Count Then selectedKey = _events(_selectedEventIndex).Key
            _events.Sort(Function(left As AgendaEventState, right As AgendaEventState)
                             Dim c As Integer = left.EventDay.CompareTo(right.EventDay)
                             If c <> 0 Then Return c
                             c = left.StartMinute.CompareTo(right.StartMinute)
                             If c <> 0 Then Return c
                             Return StringComparer.OrdinalIgnoreCase.Compare(left.Title, right.Title)
                         End Function)
            _selectedEventIndex = If(selectedKey.Length = 0, MASAgendaViewPolicy.ClampIndex(_selectedEventIndex, _events.Count), FindEventIndex(selectedKey))
            Dim visible As List(Of Integer) = GetVisibleEventIndicesForCurrentView()
            If _selectedEventIndex >= 0 AndAlso Not visible.Contains(_selectedEventIndex) Then _selectedEventIndex = -1
            _topEventIndex = MASAgendaViewPolicy.EnsureVisibleEventIndex(_selectedEventIndex, _topEventIndex, visible.Count)
        End Sub

        Private Function FindEventIndex(eventKey As String) As Integer
            Dim normalized As String = If(eventKey, String.Empty).Trim()
            For i As Integer = 0 To _events.Count - 1
                If String.Equals(_events(i).Key, normalized, StringComparison.Ordinal) Then Return i
            Next
            Return -1
        End Function

        Private Function GetSelectedEvent() As AgendaEventState
            If _selectedEventIndex < 0 OrElse _selectedEventIndex >= _events.Count Then Return Nothing
            Return _events(_selectedEventIndex)
        End Function


        Private Function IsEventVisibleInCurrentView(item As AgendaEventState) As Boolean
            If item Is Nothing Then Return False
            Dim day As Date = MASAgendaViewPolicy.NormalizeDay(item.EventDay)
            Select Case _viewMode
                Case MASAgendaViewMode.Week
                    Dim startDay As Date = MASAgendaViewPolicy.ResolveWeekStart(_day)
                    Return day >= startDay AndAlso day <= startDay.AddDays(6)
                Case MASAgendaViewMode.Month
                    Return day.Year = _day.Year AndAlso day.Month = _day.Month
                Case Else
                    Return day = _day
            End Select
        End Function

        Private Function GetVisibleEventIndicesForCurrentView() As List(Of Integer)
            Dim indices As New List(Of Integer)()
            For i As Integer = 0 To _events.Count - 1
                If IsEventVisibleInCurrentView(_events(i)) Then indices.Add(i)
            Next
            Return indices
        End Function

        Private Function GetVisibleEventCountForCurrentView() As Integer
            Dim count As Integer
            For Each item As AgendaEventState In _events
                If IsEventVisibleInCurrentView(item) Then count += 1
            Next
            Return count
        End Function

        Private Function GetEventCountForDay(day As Date) As Integer
            Dim normalized As Date = MASAgendaViewPolicy.NormalizeDay(day)
            Dim count As Integer
            For Each item As AgendaEventState In _events
                If MASAgendaViewPolicy.NormalizeDay(item.EventDay) = normalized Then count += 1
            Next
            Return count
        End Function

#End Region

    End Class

End Namespace
