Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
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 MASMasterDetailView

#Region "Rendering / Master Pane"

        Private Sub DrawMasterPane(canvas As SKCanvas,
                                   ctx As MASThemeContext,
                                   rect As SKRect,
                                   dpi As Single,
                                   plan As MASMasterDetailViewLayoutPlan,
                                   accent As SKColor,
                                   isRtl As Boolean)
            If plan Is Nothing Then Return
            DrawPaneBackground(canvas, rect, dpi, plan, accent, MasterDetailViewTokens.MasterPaneFillAlpha)
            If _items.Count = 0 Then
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, ResolveMasterEmptyText(), Inset(rect, plan.ItemPaddingPx), dpi, MASTypography.MASTextStyle.Body, MASMasterDetailViewPolicy.ResolveMutedTextColor(ctx).WithAlpha(MasterDetailViewTokens.EmptyTextAlpha), TypographyTextPrimitives.TextAlign.Center, False)
                Return
            End If

            NormalizeViewState()
            Dim rowHeight As Single = plan.ItemHeightPx
            Dim rowGap As Single = plan.ItemGapPx
            Dim body As SKRect = Inset(rect, plan.PanePaddingPx)
            Dim maxRowsBySpace As Integer = Math.Max(1, CInt(Math.Floor((body.Height + rowGap) / Math.Max(1.0F, rowHeight + rowGap))))
            _lastVisibleCount = Math.Min(plan.MaxVisibleItems, maxRowsBySpace)
            Dim visibleCount As Integer = Math.Min(_lastVisibleCount, _items.Count - _topIndex)
            If visibleCount <= 0 Then Return

            For visualIndex As Integer = 0 To visibleCount - 1
                Dim index As Integer = _topIndex + visualIndex
                Dim top As Single = body.Top + CSng(visualIndex) * (rowHeight + rowGap)
                If top + rowHeight > body.Bottom + 0.5F * dpi Then Exit For
                Dim itemRect As SKRect = PixelSnap.SnapRect(New SKRect(body.Left, top, body.Right, top + rowHeight), dpi)
                DrawMasterItem(canvas, ctx, itemRect, index, dpi, plan, accent, isRtl)
            Next
        End Sub

        Private Sub DrawMasterItem(canvas As SKCanvas,
                                   ctx As MASThemeContext,
                                   rect As SKRect,
                                   index As Integer,
                                   dpi As Single,
                                   plan As MASMasterDetailViewLayoutPlan,
                                   accent As SKColor,
                                   isRtl As Boolean)
            Dim item As MasterDetailItemState = _items(index)
            Dim selected As Boolean = index = _selectedIndex AndAlso Not ShouldSuppressSelectionFill(index)
            Dim hovered As Boolean = index = _hoverIndex
            Dim pressed As Boolean = index = _pressedIndex
            Dim fillColor As SKColor = accent.WithAlpha(MasterDetailViewTokens.ItemFillAlpha)
            If selected Then fillColor = accent.WithAlpha(MasterDetailViewTokens.ItemSelectedAlpha)
            If hovered Then fillColor = accent.WithAlpha(MasterDetailViewTokens.ItemHoverAlpha)
            If pressed Then fillColor = accent.WithAlpha(MasterDetailViewTokens.ItemPressedAlpha)

            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = fillColor}
                canvas.DrawRoundRect(rect, plan.ItemRadiusPx, plan.ItemRadiusPx, fill)
            End Using
            If selected Then
                Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(MasterDetailViewTokens.ItemSelectedStrokeAlpha)}
                    canvas.DrawRoundRect(rect, plan.ItemRadiusPx, plan.ItemRadiusPx, stroke)
                End Using
                Dim marker As SKRect = If(isRtl,
                                          New SKRect(rect.Right - 4.0F * dpi, rect.Top + 10.0F * dpi, rect.Right - 2.0F * dpi, rect.Bottom - 10.0F * dpi),
                                          New SKRect(rect.Left + 2.0F * dpi, rect.Top + 10.0F * dpi, rect.Left + 4.0F * dpi, rect.Bottom - 10.0F * dpi))
                Using markerPaint As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(230)}
                    canvas.DrawRoundRect(marker, 2.0F * dpi, 2.0F * dpi, markerPaint)
                End Using
            End If

            Dim pad As Single = plan.ItemPaddingPx
            Dim titleRect As New SKRect(rect.Left + pad, rect.Top + Math.Max(3.0F * dpi, 7.0F * plan.ResponsiveProfile.ChromeScale * dpi), rect.Right - pad, rect.Top + Math.Min(rect.Height, 30.0F * plan.ResponsiveProfile.ChromeScale * dpi))
            Dim subtitleRect As New SKRect(rect.Left + pad, titleRect.Bottom + 2.0F * plan.ResponsiveProfile.GapScale * dpi, rect.Right - pad, rect.Bottom - Math.Max(2.0F * dpi, 5.0F * plan.ResponsiveProfile.GapScale * dpi))
            Dim align As TypographyTextPrimitives.TextAlign = If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, item.Title, titleRect, dpi, MASTypography.MASTextStyle.Body, MASMasterDetailViewPolicy.ResolvePrimaryTextColor(ctx), align, False)
            If plan.ShowItemSubtitle AndAlso subtitleRect.Height > 6.0F * dpi Then
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, item.Subtitle, subtitleRect, dpi, MASTypography.MASTextStyle.Micro, MASMasterDetailViewPolicy.ResolveMutedTextColor(ctx), align, False)
            End If
            If plan.ShowBadges Then DrawBadge(canvas, ctx, rect, item.BadgeText, dpi, plan, accent, isRtl)
            _hits.Add(New MasterDetailItemHit(index, rect))
        End Sub

        Private Sub DrawBadge(canvas As SKCanvas,
                              ctx As MASThemeContext,
                              itemRect As SKRect,
                              text As String,
                              dpi As Single,
                              plan As MASMasterDetailViewLayoutPlan,
                              accent As SKColor,
                              isRtl As Boolean)
            If String.IsNullOrWhiteSpace(text) Then Return
            Dim width As Single = Math.Min(plan.BadgeMaxWidthPx, Math.Max(plan.BadgeMinWidthPx, CSng(text.Length) * 7.0F * dpi * plan.ResponsiveProfile.ContentScale + 18.0F * dpi * plan.ResponsiveProfile.ChromeScale))
            Dim rect As SKRect
            If isRtl Then
                rect = New SKRect(itemRect.Left + 10.0F * dpi, itemRect.Top + 9.0F * dpi, itemRect.Left + 10.0F * dpi + width, itemRect.Top + 31.0F * dpi)
            Else
                rect = New SKRect(itemRect.Right - 10.0F * dpi - width, itemRect.Top + 9.0F * dpi, itemRect.Right - 10.0F * dpi, itemRect.Top + 31.0F * dpi)
            End If
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(MasterDetailViewTokens.BadgeFillAlpha)}
                canvas.DrawRoundRect(rect, 11.0F * dpi, 11.0F * dpi, fill)
            End Using
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, text, rect, dpi, MASTypography.MASTextStyle.Micro, MASMasterDetailViewPolicy.ResolvePrimaryTextColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
        End Sub

#End Region

    End Class

End Namespace
