Option Strict On
Option Explicit On

Imports System
Imports SkiaSharp
Imports Nexamas.UI.Values

Namespace Nexamas.UI.Components

    Friend NotInheritable Class TopBarController

        Friend Sub UpdateLayout(item As TopBarItem,
                        hostRectPx As SKRect,
                        dpi As Single,
                        Optional leftReservedPx As Single = 0.0F)

            If item Is Nothing Then Return

            dpi = MASTopBarChromePolicy.NormalizeDpi(dpi)
            leftReservedPx = MASTopBarChromePolicy.NormalizeLeftReservedPx(leftReservedPx)

            If hostRectPx.Width <= TopBarTokens.MinimumUsablePx OrElse hostRectPx.Height <= TopBarTokens.MinimumUsablePx Then
                item.BarRectPx = SKRect.Empty
                item.DragRectPx = SKRect.Empty
                item.TitleRectPx = SKRect.Empty
                item.LogoRectPx = SKRect.Empty
                Return
            End If

            ' The caller-supplied host rectangle is the authoritative TopBar layout slot.
            ' MASApplicationWindowShell resolves that slot from the active MASSizeProfile, so
            ' clamping the renderer back to TopBarTokens.Height would silently ignore Default /
            ' Compact / Comfortable / Large / TouchFriendly TopBar sizing. TopBarTokens.Height
            ' remains the fallback contract used by callers when they need the standard slot.
            Dim barRect As SKRect = hostRectPx

            item.BarRectPx = barRect

            If barRect.Width <= TopBarTokens.MinimumUsablePx OrElse barRect.Height <= TopBarTokens.MinimumUsablePx Then
                item.DragRectPx = SKRect.Empty
                item.TitleRectPx = SKRect.Empty
                item.LogoRectPx = SKRect.Empty
                Return
            End If

            Dim padX As Single = TopBarTokens.PaddingX * dpi
            Dim padY As Single = TopBarTokens.PaddingY * dpi

            Dim leftLimit As Single = barRect.Left + padX + leftReservedPx
            Dim rightLimit As Single = barRect.Right - padX
            Dim availableWidth As Single = Math.Max(0.0F, rightLimit - leftLimit)

            item.LogoRectPx = SKRect.Empty
            item.TitleRectPx = SKRect.Empty

            If item.ShowLogo Then
                item.LogoRectPx = ResolveLogoRect(barRect, leftLimit, rightLimit, availableWidth)
            ElseIf availableWidth >= TopBarTokens.TitleMinimumWidthPx Then
                Dim titleMaxW As Single = Math.Max(0.0F, barRect.Width * TopBarTokens.TitleMaxWidthRatio)
                Dim titleW As Single = Math.Min(titleMaxW, availableWidth)

                If titleW >= TopBarTokens.TitleMinimumWidthPx Then
                    Dim titleCenter As Single = leftLimit + (availableWidth * 0.5F)
                    Dim titleLeft As Single = titleCenter - (titleW * 0.5F)
                    Dim titleRight As Single = titleLeft + titleW

                    If titleLeft < leftLimit Then
                        titleLeft = leftLimit
                        titleRight = titleLeft + titleW
                    End If

                    If titleRight > rightLimit Then
                        titleRight = rightLimit
                        titleLeft = titleRight - titleW
                    End If

                    Dim titleTop As Single = barRect.Top + padY
                    Dim titleBottom As Single = barRect.Bottom - padY

                    If titleRight - titleLeft >= TopBarTokens.TitleMinimumWidthPx AndAlso titleBottom - titleTop >= TopBarTokens.TitleMinimumHeightPx Then
                        item.TitleRectPx = New SKRect(titleLeft, titleTop, titleRight, titleBottom)
                    End If
                End If
            End If

            item.DragRectPx = BuildDragRect(barRect, leftLimit, rightLimit, padY)
        End Sub

        Private Shared Function ResolveLogoRect(barRect As SKRect,
                                                leftLimit As Single,
                                                rightLimit As Single,
                                                availableWidth As Single) As SKRect

            If availableWidth < TopBarTokens.LogoMinimumAvailableWidthPx OrElse barRect.Height <= TopBarTokens.MinimumUsablePx Then Return SKRect.Empty

            Dim logoAspect As Single = TopBarTokens.LogoAspectWidth / TopBarTokens.LogoAspectHeight
            Dim logoH As Single = barRect.Height * TopBarTokens.LogoHeightRatio
            Dim logoW As Single = logoH * logoAspect
            Dim maxLogoW As Single = Math.Min(barRect.Width * TopBarTokens.LogoMaxBarWidthRatio, availableWidth * TopBarTokens.LogoMaxAvailableWidthRatio)

            If maxLogoW < TopBarTokens.LogoMinimumAvailableWidthPx Then Return SKRect.Empty

            If logoW > maxLogoW Then
                logoW = maxLogoW
                logoH = logoW / logoAspect
            End If

            Dim logoCenterX As Single = leftLimit + (availableWidth * 0.5F)
            Dim logoLeft As Single = logoCenterX - (logoW * 0.5F)
            Dim logoRight As Single = logoLeft + logoW

            If logoLeft < leftLimit Then
                logoLeft = leftLimit
                logoRight = logoLeft + logoW
            End If

            If logoRight > rightLimit Then
                logoRight = rightLimit
                logoLeft = logoRight - logoW
            End If

            Dim logoTop As Single = barRect.MidY - (logoH * 0.5F)

            Return New SKRect(
                logoLeft,
                logoTop,
                logoLeft + logoW,
                logoTop + logoH)
        End Function

        Private Shared Function BuildDragRect(barRect As SKRect, leftLimit As Single, rightLimit As Single, padY As Single) As SKRect
            Dim t As Single = barRect.Top + padY
            Dim b As Single = barRect.Bottom - padY

            If rightLimit - leftLimit < TopBarTokens.TitleMinimumWidthPx OrElse b - t < TopBarTokens.TitleMinimumHeightPx Then Return SKRect.Empty
            Return New SKRect(leftLimit, t, rightLimit, b)
        End Function

        Friend Sub UpdateHover(item As TopBarItem, ptPx As SKPoint)
            If item Is Nothing Then Return
            item.IsHoveringDragZone = item.HitTestDragZone(ptPx)
        End Sub

    End Class

End Namespace