Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports Nexamas.UI.General
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASAgendaView

#Region "Range Views"

        Friend NotInheritable Class AgendaRangeViewEvidence
            Friend Sub New(mode As MASAgendaViewMode,
                           rangeStart As Date,
                           rangeEnd As Date,
                           cellCount As Integer,
                           visibleEventCount As Integer,
                           selectedDayCount As Integer)
                Me.Mode = mode
                Me.RangeStart = MASAgendaViewPolicy.NormalizeDay(rangeStart)
                Me.RangeEnd = MASAgendaViewPolicy.NormalizeDay(rangeEnd)
                Me.CellCount = Math.Max(0, cellCount)
                Me.VisibleEventCount = Math.Max(0, visibleEventCount)
                Me.SelectedDayCount = Math.Max(0, selectedDayCount)
            End Sub

            Friend ReadOnly Property Mode As MASAgendaViewMode
            Friend ReadOnly Property RangeStart As Date
            Friend ReadOnly Property RangeEnd As Date
            Friend ReadOnly Property CellCount As Integer
            Friend ReadOnly Property VisibleEventCount As Integer
            Friend ReadOnly Property SelectedDayCount As Integer
        End Class

        Private Sub DrawAgendaRangeBody(canvas As SKCanvas,
                                        ctx As MASThemeContext,
                                        body As SKRect,
                                        dpi As Single,
                                        isRtl As Boolean,
                                        plan As MASAgendaViewLayoutPlan)
            If canvas Is Nothing OrElse body.Width <= 1.0F OrElse body.Height <= 1.0F Then Return
            Dim mode As MASAgendaViewMode = MASAgendaViewPolicy.NormalizeViewMode(_viewMode)
            If mode = MASAgendaViewMode.Day Then Return

            Dim gridStart As Date = If(mode = MASAgendaViewMode.Month,
                                       MASAgendaViewPolicy.ResolveMonthGridStart(_day),
                                       MASAgendaViewPolicy.ResolveWeekStart(_day))
            Dim cellCount As Integer = MASAgendaViewPolicy.ResolveRangeCellCount(mode)
            Dim columns As Integer = 7
            Dim rows As Integer = Math.Max(1, CInt(Math.Ceiling(CDbl(cellCount) / CDbl(columns))))
            Dim gap As Single = Math.Max(2.0F * dpi, If(plan Is Nothing, 4.0F * dpi, plan.RowGapPx * 0.45F))
            Dim cellWidth As Single = Math.Max(1.0F, (body.Width - gap * CSng(columns - 1)) / CSng(columns))
            Dim cellHeight As Single = Math.Max(1.0F, (body.Height - gap * CSng(rows - 1)) / CSng(rows))
            Dim primary As SKColor = MASAgendaViewPolicy.ResolvePrimaryTextColor(ctx)
            Dim muted As SKColor = MASAgendaViewPolicy.ResolveMutedTextColor(ctx)
            Dim accent As SKColor = MASAgendaViewPolicy.ResolveAccentColor(ctx)

            For cell As Integer = 0 To cellCount - 1
                Dim visualColumn As Integer = cell Mod columns
                If isRtl Then visualColumn = columns - visualColumn - 1
                Dim row As Integer = cell \ columns
                Dim left As Single = body.Left + CSng(visualColumn) * (cellWidth + gap)
                Dim top As Single = body.Top + CSng(row) * (cellHeight + gap)
                Dim rect As SKRect = PixelSnap.SnapRect(New SKRect(left, top, left + cellWidth, top + cellHeight), dpi)
                Dim cellDay As Date = gridStart.AddDays(cell)
                Dim inScope As Boolean = If(mode = MASAgendaViewMode.Month,
                                            cellDay.Month = _day.Month AndAlso cellDay.Year = _day.Year,
                                            True)
                Dim selectedDay As Boolean = (cellDay = _day)
                Dim today As Boolean = (cellDay = ResolveNow().Date)

                Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(If(selectedDay, CByte(28), If(today, CByte(18), CByte(8))))}
                    canvas.DrawRoundRect(rect, 12.0F * dpi, 12.0F * dpi, fill)
                End Using
                Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(If(selectedDay, CByte(88), CByte(32)))}
                    canvas.DrawRoundRect(Inset(rect, 0.5F * dpi), 12.0F * dpi, 12.0F * dpi, stroke)
                End Using

                Dim dayText As String = If(mode = MASAgendaViewMode.Week,
                                           cellDay.ToString("ddd d", CultureInfo.CurrentCulture),
                                           cellDay.Day.ToString(CultureInfo.CurrentCulture))
                Dim labelRect As New SKRect(rect.Left + 7.0F * dpi, rect.Top + 5.0F * dpi, rect.Right - 7.0F * dpi, rect.Top + 25.0F * dpi)
                Dim labelColor As SKColor = If(inScope, primary, muted.WithAlpha(92))
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, dayText, labelRect, dpi, MASTypography.MASTextStyle.Micro, labelColor, If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)

                DrawRangeCellEvents(canvas, ctx, rect, dpi, isRtl, cellDay, inScope, plan)
            Next
        End Sub

        Private Sub DrawRangeCellEvents(canvas As SKCanvas,
                                        ctx As MASThemeContext,
                                        rect As SKRect,
                                        dpi As Single,
                                        isRtl As Boolean,
                                        cellDay As Date,
                                        inScope As Boolean,
                                        plan As MASAgendaViewLayoutPlan)
            Dim normalizedDay As Date = MASAgendaViewPolicy.NormalizeDay(cellDay)
            Dim visible As New List(Of Integer)()
            For i As Integer = 0 To _events.Count - 1
                If MASAgendaViewPolicy.NormalizeDay(_events(i).EventDay) = normalizedDay Then visible.Add(i)
            Next
            If visible.Count = 0 Then Return

            Dim accent As SKColor = MASAgendaViewPolicy.ResolveAccentColor(ctx)
            Dim primary As SKColor = MASAgendaViewPolicy.ResolvePrimaryTextColor(ctx)
            Dim muted As SKColor = MASAgendaViewPolicy.ResolveMutedTextColor(ctx)
            Dim top As Single = rect.Top + 29.0F * dpi
            Dim chipHeight As Single = Math.Max(16.0F * dpi, If(plan Is Nothing, 18.0F * dpi, plan.TimePillHeightPx * 0.76F))
            Dim gap As Single = Math.Max(2.0F * dpi, 3.0F * dpi)
            Dim maxChips As Integer = Math.Max(1, CInt(Math.Floor(CDbl(Math.Max(1.0F, rect.Bottom - top - 4.0F * dpi)) / CDbl(chipHeight + gap))))
            maxChips = Math.Min(maxChips, 4)
            Dim shown As Integer = Math.Min(maxChips, visible.Count)
            For n As Integer = 0 To shown - 1
                Dim eventIndex As Integer = visible(n)
                Dim item As AgendaEventState = _events(eventIndex)
                Dim chip As SKRect = PixelSnap.SnapRect(New SKRect(rect.Left + 7.0F * dpi,
                                                                    top + CSng(n) * (chipHeight + gap),
                                                                    rect.Right - 7.0F * dpi,
                                                                    top + CSng(n) * (chipHeight + gap) + chipHeight), dpi)
                If chip.Width <= 1.0F OrElse chip.Height <= 1.0F Then Continue For
                _eventHitRects.Add(New AgendaEventHit(eventIndex, chip))
                Dim selected As Boolean = (_selectedEventIndex = eventIndex)
                Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(If(selected, CByte(96), If(inScope, CByte(46), CByte(22))))}
                    canvas.DrawRoundRect(chip, chip.Height * 0.5F, chip.Height * 0.5F, fill)
                End Using
                Dim textRect As SKRect = Inset(chip, 5.0F * dpi)
                Dim text As String = MASAgendaViewPolicy.BuildTimeText(item.StartMinute, item.EndMinute) & "  " & item.Title
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, text, textRect, dpi, MASTypography.MASTextStyle.Micro, If(inScope, primary, muted), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
            Next
            If visible.Count > shown Then
                Dim moreRect As New SKRect(rect.Left + 7.0F * dpi,
                                           top + CSng(shown) * (chipHeight + gap),
                                           rect.Right - 7.0F * dpi,
                                           Math.Min(rect.Bottom - 2.0F * dpi, top + CSng(shown) * (chipHeight + gap) + chipHeight))
                If moreRect.Height > 8.0F * dpi Then
                    Dim moreText As String = "+" & (visible.Count - shown).ToString(CultureInfo.CurrentCulture) & " more"
                    TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, moreText, moreRect, dpi, MASTypography.MASTextStyle.Micro, muted, TypographyTextPrimitives.TextAlign.Center, False)
                End If
            End If
        End Sub

        Friend Function CreateRangeViewEvidenceForTests(mode As MASAgendaViewMode) As AgendaRangeViewEvidence
            Dim previousMode As MASAgendaViewMode = _viewMode
            Try
                _viewMode = MASAgendaViewPolicy.NormalizeViewMode(mode)
                Dim startDay As Date
                Dim endDay As Date
                Dim cellCount As Integer = MASAgendaViewPolicy.ResolveRangeCellCount(_viewMode)
                If _viewMode = MASAgendaViewMode.Month Then
                    startDay = MASAgendaViewPolicy.ResolveMonthGridStart(_day)
                    endDay = startDay.AddDays(cellCount - 1)
                ElseIf _viewMode = MASAgendaViewMode.Week Then
                    startDay = MASAgendaViewPolicy.ResolveWeekStart(_day)
                    endDay = startDay.AddDays(6)
                Else
                    startDay = _day
                    endDay = _day
                End If
                Return New AgendaRangeViewEvidence(_viewMode, startDay, endDay, cellCount, GetVisibleEventCountForCurrentView(), GetEventCountForDay(_day))
            Finally
                _viewMode = previousMode
            End Try
        End Function

#End Region

    End Class

End Namespace
