Option Strict On
Option Explicit On

Imports Nexamas.UI.Theming
Imports SkiaSharp

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Rendering context passed to reusable surface materials.
    ''' It carries platform theme data, the consolidated reusable surface theme profile,
    ''' target geometry, visual state, surface role, opacity, and strength levels.
    ''' It deliberately does not expose PanelShell-specific theme contracts.
    ''' </summary>
    Friend NotInheritable Class MASSurfaceMaterialContext
        Friend ReadOnly Property ThemeContext As MASThemeContext
        Friend ReadOnly Property SurfaceTheme As MASSurfaceThemeProfile
        Friend ReadOnly Property BoundsPx As SKRect
        Friend ReadOnly Property CornerRadiusPx As Single
        Friend ReadOnly Property Opacity As Single
        Friend ReadOnly Property VisualState As MASSurfaceVisualState
        Friend ReadOnly Property SurfaceRole As MASSurfaceRole
        Friend ReadOnly Property SurfaceStrengthLevel As Integer
        Friend ReadOnly Property Dpi As Single

        Friend Sub New(themeContext As MASThemeContext,
                       surfaceTheme As MASSurfaceThemeProfile,
                       surfaceStrengthLevel As Integer,
                       dpi As Single,
                       Optional boundsPx As SKRect = Nothing,
                       Optional cornerRadiusPx As Single = 0.0F,
                       Optional opacity As Single = 1.0F,
                       Optional visualState As MASSurfaceVisualState = MASSurfaceVisualState.Normal,
                       Optional surfaceRole As MASSurfaceRole = MASSurfaceRole.Unknown)

            Me.ThemeContext = themeContext
            Me.SurfaceTheme = If(surfaceTheme, MASSurfaceThemeProfileResolver.Resolve(themeContext))
            Me.BoundsPx = boundsPx
            Me.CornerRadiusPx = SafeRadius(cornerRadiusPx)
            Me.Opacity = Clamp01(opacity)
            Me.VisualState = visualState
            Me.SurfaceRole = surfaceRole
            Me.SurfaceStrengthLevel = ClampLevel(surfaceStrengthLevel)
            Me.Dpi = SafeDpi(dpi, themeContext)
        End Sub

        Friend Shared Function Create(Optional dpi As Single = 1.0F,
                                      Optional themeContext As MASThemeContext = Nothing,
                                      Optional surfaceTheme As MASSurfaceThemeProfile = Nothing,
                                      Optional surfaceStrengthLevel As Integer = 3,
                                      Optional boundsPx As SKRect = Nothing,
                                      Optional cornerRadiusPx As Single = 0.0F,
                                      Optional surfaceRole As MASSurfaceRole = MASSurfaceRole.Unknown) As MASSurfaceMaterialContext

            Return New MASSurfaceMaterialContext(
                themeContext:=themeContext,
                surfaceTheme:=surfaceTheme,
                surfaceStrengthLevel:=surfaceStrengthLevel,
                dpi:=dpi,
                boundsPx:=boundsPx,
                cornerRadiusPx:=cornerRadiusPx,
                opacity:=1.0F,
                visualState:=MASSurfaceVisualState.Normal,
                surfaceRole:=surfaceRole)
        End Function

        Private Shared Function ClampLevel(value As Integer) As Integer
            If value < 1 Then Return 1
            If value > 6 Then Return 6
            Return value
        End Function

        Private Shared Function Clamp01(value As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) Then Return 1.0F
            If value < 0.0F Then Return 0.0F
            If value > 1.0F Then Return 1.0F
            Return value
        End Function

        Private Shared Function SafeRadius(value As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) OrElse value < 0.0F Then Return 0.0F
            Return value
        End Function

        Private Shared Function SafeDpi(value As Single,
                                        themeContext As MASThemeContext) As Single
            Dim resolvedDpi As Single = value
            If themeContext IsNot Nothing AndAlso themeContext.Dpi > 0.0F Then resolvedDpi = themeContext.Dpi
            If resolvedDpi <= 0.0F OrElse Single.IsNaN(resolvedDpi) OrElse Single.IsInfinity(resolvedDpi) Then Return 1.0F
            Return resolvedDpi
        End Function
    End Class

End Namespace
