Option Strict On
Option Explicit On

Imports System
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 MASSplitView

#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

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

            Dim plan As MASSplitViewLayoutPlan = MASSplitViewLayoutPlan.Create(ctx, bounds, SizeIntent)
            Dim dpi As Single = plan.MetricDpi
            _lastDpi = dpi
            _primitives.DrawCardSurface(canvas, ctx, bounds, pixelDpi, Me.ArchitectureContract, MASCardVisualStyle.Secondary)
            _contentRect = PixelSnap.SnapRect(Inset(bounds, plan.PaddingPx), pixelDpi)
            If _contentRect.Width <= 1.0F OrElse _contentRect.Height <= 1.0F Then Return

            Dim isRtl As Boolean = MASSplitViewPolicy.ResolveRightToLeft()
            Dim accent As SKColor = MASSplitViewPolicy.ResolveAccentColor(ctx)
            DrawHeader(canvas, ctx, _contentRect, dpi, isRtl)
            DrawPanes(canvas, ctx, _contentRect, dpi, accent, isRtl)
            DrawFooter(canvas, ctx, _contentRect, dpi, isRtl)
        End Sub

        Private Sub DrawHeader(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               content As SKRect,
                               dpi As Single,
                               isRtl As Boolean)
            Dim header As New SKRect(content.Left, content.Top, content.Right, content.Top + SplitViewTokens.HeaderHeightDip * dpi)
            Dim summaryWidth As Single = Math.Min(320.0F * dpi, header.Width * 0.44F)
            Dim titleRect As SKRect = If(isRtl,
                                         New SKRect(header.Left + summaryWidth, header.Top, header.Right, header.Bottom),
                                         New SKRect(header.Left, header.Top, header.Right - summaryWidth, header.Bottom))
            Dim summaryRect As SKRect = If(isRtl,
                                           New SKRect(header.Left, header.Top, header.Left + summaryWidth, header.Bottom),
                                           New SKRect(header.Right - summaryWidth, header.Top, header.Right, header.Bottom))
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, _title, titleRect, dpi, MASTypography.MASTextStyle.Title, MASSplitViewPolicy.ResolvePrimaryTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, SummaryText, summaryRect, dpi, MASTypography.MASTextStyle.Micro, MASSplitViewPolicy.ResolveMutedTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Left, TypographyTextPrimitives.TextAlign.Right), False)
        End Sub

        Private Sub DrawPanes(canvas As SKCanvas,
                              ctx As MASThemeContext,
                              content As SKRect,
                              dpi As Single,
                              accent As SKColor,
                              isRtl As Boolean)
            Dim top As Single = content.Top + SplitViewTokens.HeaderHeightDip * dpi + SplitViewTokens.PaneGapDip * dpi
            Dim bottom As Single = content.Bottom - SplitViewTokens.FooterHeightDip * dpi - SplitViewTokens.PaneGapDip * dpi
            _bodyRect = PixelSnap.SnapRect(New SKRect(content.Left, top, content.Right, bottom), dpi)
            If _bodyRect.Width <= 1.0F OrElse _bodyRect.Height <= 1.0F Then Return

            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(SplitViewTokens.SurfaceFillAlpha)}
                canvas.DrawRoundRect(_bodyRect, SplitViewTokens.PaneRadiusDip * dpi, SplitViewTokens.PaneRadiusDip * dpi, fill)
            End Using
            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(SplitViewTokens.SurfaceStrokeAlpha)}
                canvas.DrawRoundRect(_bodyRect, SplitViewTokens.PaneRadiusDip * dpi, SplitViewTokens.PaneRadiusDip * dpi, stroke)
            End Using

            Dim geometry As SplitViewGeometry = BuildGeometry(_bodyRect, dpi, isRtl)
            _leftDividerRect = geometry.LeftDivider
            _rightDividerRect = geometry.RightDivider

            DrawPane(canvas, ctx, geometry.LeftPane, _leftPaneTitle, _leftPaneText, _leftPaneCollapsed, dpi, accent, isRtl, "L", "left", MASHostedContentSlotKind.SplitViewLeftPane)
            DrawDivider(canvas, geometry.LeftDivider, dpi, accent, SplitDividerSide.Left)
            DrawPane(canvas, ctx, geometry.ContentPane, _contentPaneTitle, _contentPaneText, False, dpi, accent, isRtl, "C", "content", MASHostedContentSlotKind.SplitViewContentPane)
            DrawDivider(canvas, geometry.RightDivider, dpi, accent, SplitDividerSide.Right)
            DrawPane(canvas, ctx, geometry.RightPane, _rightPaneTitle, _rightPaneText, _rightPaneCollapsed, dpi, accent, isRtl, "R", "right", MASHostedContentSlotKind.SplitViewRightPane)
            DrawPaneRevealMotionOverlay(canvas, geometry, dpi, accent)
        End Sub

        Private Sub DrawPane(canvas As SKCanvas,
                             ctx As MASThemeContext,
                             rect As SKRect,
                             title As String,
                             text As String,
                             collapsed As Boolean,
                             dpi As Single,
                             accent As SKColor,
                             isRtl As Boolean,
                             glyph As String,
                             paneKey As String,
                             slotKind As MASHostedContentSlotKind)
            If rect.Width <= 1.0F OrElse rect.Height <= 1.0F Then Return
            Dim snapped As SKRect = PixelSnap.SnapRect(rect, dpi)
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(If(collapsed, SplitViewTokens.PaneHoverAlpha, SplitViewTokens.PaneFillAlpha))}
                canvas.DrawRoundRect(snapped, SplitViewTokens.PaneRadiusDip * dpi, SplitViewTokens.PaneRadiusDip * dpi, fill)
            End Using
            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(SplitViewTokens.PaneStrokeAlpha)}
                canvas.DrawRoundRect(snapped, SplitViewTokens.PaneRadiusDip * dpi, SplitViewTokens.PaneRadiusDip * dpi, stroke)
            End Using

            Dim padding As Single = SplitViewTokens.PanePaddingDip * dpi
            Dim inner As SKRect = Inset(snapped, padding)
            If inner.Width <= 1.0F OrElse inner.Height <= 1.0F Then Return
            Dim align As TypographyTextPrimitives.TextAlign = If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left)

            If collapsed OrElse inner.Width < 90.0F * dpi Then
                Dim chip As New SKRect(inner.Left, inner.Top, inner.Right, Math.Min(inner.Bottom, inner.Top + SplitViewTokens.ChipHeightDip * dpi))
                Using chipFill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(SplitViewTokens.ChipFillAlpha)}
                    canvas.DrawRoundRect(chip, 999.0F, 999.0F, chipFill)
                End Using
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, glyph, chip, dpi, MASTypography.MASTextStyle.Micro, MASSplitViewPolicy.ResolvePrimaryTextColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
                Dim labelRect As New SKRect(inner.Left, chip.Bottom + 8.0F * dpi, inner.Right, Math.Min(inner.Bottom, chip.Bottom + 34.0F * dpi))
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, title, labelRect, dpi, MASTypography.MASTextStyle.Micro, MASSplitViewPolicy.ResolveMutedTextColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
                PlaceSplitViewHostedContent(paneKey, inner, dpi, False)
                Return
            End If

            Dim titleRect As New SKRect(inner.Left, inner.Top, inner.Right, inner.Top + 30.0F * dpi)
            Dim textRect As New SKRect(inner.Left, titleRect.Bottom + 6.0F * dpi, inner.Right, titleRect.Bottom + 32.0F * dpi)
            Dim helperRect As New SKRect(inner.Left, textRect.Bottom + 8.0F * dpi, inner.Right, textRect.Bottom + 30.0F * dpi)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, title, titleRect, dpi, MASTypography.MASTextStyle.Body, MASSplitViewPolicy.ResolvePrimaryTextColor(ctx), align, False)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, text, textRect, dpi, MASTypography.MASTextStyle.Micro, MASSplitViewPolicy.ResolveMutedTextColor(ctx), align, False)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, "Resizable surface", helperRect, dpi, MASTypography.MASTextStyle.Micro, MASSplitViewPolicy.ResolveMutedTextColor(ctx).WithAlpha(SplitViewTokens.FooterTextAlpha), align, False)
            DrawPaneContentHints(canvas, snapped, dpi, accent)
            PlaceSplitViewHostedContent(paneKey, inner, dpi, True)
        End Sub

        Private Sub DrawDivider(canvas As SKCanvas,
                                rect As SKRect,
                                dpi As Single,
                                accent As SKColor,
                                side As SplitDividerSide)
            If rect.Width <= 1.0F OrElse rect.Height <= 1.0F Then Return
            Dim visualWidth As Single = SplitViewTokens.DividerVisualWidthDip * dpi
            Dim centerX As Single = rect.MidX
            Dim track As New SKRect(centerX - Math.Max(1.0F, dpi),
                                    rect.Top + 16.0F * dpi,
                                    centerX + Math.Max(1.0F, dpi),
                                    rect.Bottom - 16.0F * dpi)
            Using trackFill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(SplitViewTokens.DividerTrackAlpha)}
                canvas.DrawRoundRect(track, 999.0F, 999.0F, trackFill)
            End Using
            Dim visual As New SKRect(centerX - visualWidth * 0.5F,
                                     rect.MidY - Math.Min(rect.Height * 0.38F, 120.0F * dpi),
                                     centerX + visualWidth * 0.5F,
                                     rect.MidY + Math.Min(rect.Height * 0.38F, 120.0F * dpi))
            Dim alpha As Byte = SplitViewTokens.DividerAlpha
            If _hoverDivider = side Then alpha = SplitViewTokens.DividerHoverAlpha
            If _activeDivider = side Then alpha = SplitViewTokens.DividerActiveAlpha
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(alpha)}
                canvas.DrawRoundRect(visual, 999.0F, 999.0F, fill)
            End Using
        End Sub

        Private Sub DrawFooter(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               content As SKRect,
                               dpi As Single,
                               isRtl As Boolean)
            Dim footer As SKRect = PixelSnap.SnapRect(New SKRect(content.Left, content.Bottom - SplitViewTokens.FooterHeightDip * dpi, content.Right, content.Bottom), dpi)
            Dim accent As SKColor = MASSplitViewPolicy.ResolveAccentColor(ctx)
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(SplitViewTokens.FooterFillAlpha)}
                canvas.DrawRoundRect(footer, 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(SplitViewTokens.FooterStrokeAlpha)}
                canvas.DrawRoundRect(footer, 12.0F * dpi, 12.0F * dpi, stroke)
            End Using
            Dim inner As SKRect = New SKRect(footer.Left + 10.0F * dpi, footer.Top, footer.Right - 10.0F * dpi, footer.Bottom)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, SplitViewTokens.BoundaryText, inner, dpi, MASTypography.MASTextStyle.Micro, MASSplitViewPolicy.ResolveMutedTextColor(ctx).WithAlpha(SplitViewTokens.FooterTextAlpha), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
        End Sub

        Private Sub DrawPaneContentHints(canvas As SKCanvas, rect As SKRect, dpi As Single, accent As SKColor)
            If rect.Width < 120.0F * dpi OrElse rect.Height < 118.0F * dpi Then Return
            Dim left As Single = rect.Left + SplitViewTokens.PanePaddingDip * dpi
            Dim right As Single = rect.Right - SplitViewTokens.PanePaddingDip * dpi
            Dim y As Single = rect.Bottom - 46.0F * dpi
            If y <= rect.Top + 84.0F * dpi Then Return
            Dim width As Single = right - left
            Dim first As New SKRect(left, y, left + Math.Min(width * 0.62F, 170.0F * dpi), y + 9.0F * dpi)
            Dim second As New SKRect(left, first.Bottom + 8.0F * dpi, left + Math.Min(width * 0.44F, 128.0F * dpi), first.Bottom + 17.0F * dpi)
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(SplitViewTokens.ChipFillAlpha)}
                canvas.DrawRoundRect(first, 999.0F, 999.0F, fill)
            End Using
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(CByte(Math.Max(12, CInt(SplitViewTokens.ChipFillAlpha) - 10)))}
                canvas.DrawRoundRect(second, 999.0F, 999.0F, fill)
            End Using
        End Sub

#End Region

    End Class

End Namespace
