Option Strict On
Option Explicit On

Imports System
Imports System.Windows.Forms
Imports System.Collections.Generic
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
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.Controls

    Partial Public NotInheritable Class MASNotificationPanel

#Region "Rendering"

        Protected Overrides Sub Render(canvas As SKCanvas,
                                       ctx As MASThemeContext,
                                       pixelBounds As SKRect)
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If pixelBounds.Width <= 1.0F OrElse pixelBounds.Height <= 1.0F Then Return
            _contract.AssertConsumable()

            Dim pixelDpi As Single = PixelSnap.SafeDpi(ctx.Dpi)
            Dim bounds As SKRect = PixelSnap.SnapRect(pixelBounds, pixelDpi)
            If bounds.Width <= 1.0F OrElse bounds.Height <= 1.0F Then Return

            Dim plan As MASNotificationPanelLayoutPlan = MASNotificationPanelLayoutPlan.Create(ctx, bounds, SizeIntent)
            Dim dpi As Single = plan.MetricDpi
            _primitives.DrawCardSurface(canvas, ctx, bounds, pixelDpi, _contract, MASCardVisualStyle.Secondary)
            DrawHeader(canvas, ctx, bounds, dpi)

            Dim content As SKRect = plan.ContentRectPx
            If content.Width <= 1.0F OrElse content.Height <= 1.0F Then Return

            _hits.Clear()
            If _items.Count = 0 Then
                DrawEmptyState(canvas, ctx, content, dpi)
                Return
            End If

            DrawRows(canvas, ctx, content, dpi)
        End Sub

        Private Sub DrawHeader(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               bounds As SKRect,
                               dpi As Single)
            Dim left As Single = bounds.Left + NotificationPanelTokens.PaddingLeftDip * dpi
            Dim top As Single = bounds.Top + NotificationPanelTokens.PaddingTopDip * dpi
            Dim right As Single = bounds.Right - NotificationPanelTokens.PaddingRightDip * dpi
            Dim header As New SKRect(left, top, right, top + NotificationPanelTokens.HeaderHeightDip * dpi)
            If header.Width <= 1.0F OrElse header.Height <= 1.0F Then Return

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=ResolveTitleText(),
                bounds:=header,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Title,
                color:=ResolveTitleColor(ctx),
                align:=TypographyTextPrimitives.TextAlign.Left,
                drawShadow:=False)

            Dim countText As String = ResolveCountText()
            If String.IsNullOrWhiteSpace(countText) Then Return

            Dim pillWidth As Single = Math.Min(header.Width * 0.42F, Math.Max(54.0F * dpi, countText.Length * 8.0F * dpi + 22.0F * dpi))
            Dim pillHeight As Single = NotificationPanelTokens.HeaderBadgeHeightDip * dpi
            Dim pill As New SKRect(header.Right - pillWidth,
                                   header.MidY - pillHeight / 2.0F,
                                   header.Right,
                                   header.MidY + pillHeight / 2.0F)
            DrawCountPill(canvas, ctx, pill, countText, dpi)
        End Sub

        Private Sub DrawCountPill(canvas As SKCanvas,
                                  ctx As MASThemeContext,
                                  bounds As SKRect,
                                  text As String,
                                  dpi As Single)
            Dim accent As SKColor = ResolveAccentColor(ctx)
            Dim radius As Single = Math.Max(2.0F, bounds.Height / 2.0F)
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(NotificationPanelTokens.CountPillFillAlpha)}
                canvas.DrawRoundRect(bounds, radius, radius, fill)
            End Using

            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = 1.0F * dpi, .Color = accent.WithAlpha(NotificationPanelTokens.CountPillStrokeAlpha)}
                canvas.DrawRoundRect(bounds, radius, radius, stroke)
            End Using

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=text,
                bounds:=bounds,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Micro,
                color:=ResolveTitleColor(ctx),
                align:=TypographyTextPrimitives.TextAlign.Center,
                drawShadow:=False)
        End Sub

        Private Sub DrawEmptyState(canvas As SKCanvas,
                                   ctx As MASThemeContext,
                                   bounds As SKRect,
                                   dpi As Single)
            Dim accent As SKColor = ResolveAccentColor(ctx)
            Dim iconSize As Single = NotificationPanelTokens.EmptyIconDiameterDip * dpi
            Dim icon As New SKRect(bounds.MidX - iconSize / 2.0F,
                                   bounds.Top + NotificationPanelTokens.EmptyIconTopDip * dpi,
                                   bounds.MidX + iconSize / 2.0F,
                                   bounds.Top + NotificationPanelTokens.EmptyIconTopDip * dpi + iconSize)
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(NotificationPanelTokens.EmptyIconFillAlpha)}
                canvas.DrawOval(icon, fill)
            End Using
            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, iconSize * 0.065F), .Color = accent.WithAlpha(NotificationPanelTokens.EmptyIconStrokeAlpha)}
                canvas.DrawArc(icon, 205.0F, 130.0F, False, stroke)
                canvas.DrawLine(icon.MidX, icon.Top + icon.Height * 0.28F, icon.MidX, icon.Bottom - icon.Height * 0.28F, stroke)
            End Using

            Dim titleRect As New SKRect(bounds.Left,
                                        icon.Bottom + NotificationPanelTokens.EmptyTitleGapDip * dpi,
                                        bounds.Right,
                                        icon.Bottom + (NotificationPanelTokens.EmptyTitleGapDip + NotificationPanelTokens.EmptyTitleHeightDip) * dpi)
            Dim messageRect As New SKRect(bounds.Left,
                                          titleRect.Bottom + NotificationPanelTokens.EmptyMessageGapDip * dpi,
                                          bounds.Right,
                                          titleRect.Bottom + (NotificationPanelTokens.EmptyMessageGapDip + NotificationPanelTokens.EmptyMessageHeightDip) * dpi)

            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, ResolveEmptyTitleText(), titleRect, dpi, MASTypography.MASTextStyle.Small, ResolveTitleColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, ResolveEmptyMessageText(), messageRect, dpi, MASTypography.MASTextStyle.Body, ResolveMessageColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
        End Sub

        Private Sub DrawRows(canvas As SKCanvas,
                             ctx As MASThemeContext,
                             bounds As SKRect,
                             dpi As Single)
            Dim rowHeight As Single = NotificationPanelTokens.RowHeightDip * dpi
            Dim rowGap As Single = NotificationPanelTokens.RowGapDip * dpi
            Dim maxRows As Integer = Math.Max(1, CInt(Math.Floor((bounds.Height + rowGap) / Math.Max(1.0F, rowHeight + rowGap))))
            Dim rowsToDraw As Integer = MASNotificationPanelContentPolicy.NormalizeVisibleRows(_items.Count, maxRows)

            For i As Integer = 0 To rowsToDraw - 1
                Dim y As Single = bounds.Top + i * (rowHeight + rowGap)
                Dim row As New SKRect(bounds.Left, y, bounds.Right, y + rowHeight)
                row = ResolveNotificationPanelMutationRowRect(row, dpi, i)
                DrawRow(canvas, ctx, row, dpi, _items(i), i)
            Next
        End Sub

#End Region
    End Class

End Namespace
