' SSOT-V2 Signature: This class/file follows the SSOT-V2 architecture.
Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.General
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Rendering

    Partial Friend NotInheritable Class MASVisualPrimitivesPainter

#Region "Card / Button / Chip / Bar façade"

        Friend Structure ButtonChromeSpec
            Friend FillTop As SKColor
            Friend FillBottom As SKColor
            Friend BorderOuter As SKColor
            Friend BorderInner As SKColor
            Friend InnerHighlight As SKColor
            Friend InnerShade As SKColor
            Friend MaterialWash As SKColor
            Friend BodyGlow As SKColor
            Friend TopSheen As SKColor
        End Structure

        Friend Shared Function BuildButtonChromeSpec(theme As MASButtonSurfaceTheme) As ButtonChromeSpec

            Return New ButtonChromeSpec With {
                .FillTop = theme.FillTop,
                .FillBottom = theme.FillBottom,
                .BorderOuter = theme.BorderOuter,
                .BorderInner = theme.BorderInner,
                .InnerHighlight = theme.InnerHighlight,
                .InnerShade = theme.InnerShade,
                .MaterialWash = theme.MaterialWash,
                .BodyGlow = theme.BodyGlow,
                .TopSheen = theme.TopSheen
            }

        End Function

        Friend Shared Function BuildButtonChromeSpec(theme As MASButtonSurfaceTheme,
                                                      state As MASVisualInteractionState) As ButtonChromeSpec

            Dim baseSpec As ButtonChromeSpec = BuildButtonChromeSpec(theme)

            Dim chromeSpec As New MASActionChromePainter.MASActionChromeSpec With {
                .FillTop = baseSpec.FillTop,
                .FillBottom = baseSpec.FillBottom,
                .BorderOuter = baseSpec.BorderOuter,
                .BorderInner = baseSpec.BorderInner,
                .InnerHighlight = baseSpec.InnerHighlight,
                .InnerShade = baseSpec.InnerShade,
                .MaterialWash = baseSpec.MaterialWash,
                .BodyGlow = baseSpec.BodyGlow,
                .TopSheen = baseSpec.TopSheen
            }

            chromeSpec = MASActionChromePainter.MorphActionChromeSpecByState(chromeSpec, state)

            Return New ButtonChromeSpec With {
                .FillTop = chromeSpec.FillTop,
                .FillBottom = chromeSpec.FillBottom,
                .BorderOuter = chromeSpec.BorderOuter,
                .BorderInner = chromeSpec.BorderInner,
                .InnerHighlight = chromeSpec.InnerHighlight,
                .InnerShade = chromeSpec.InnerShade,
                .MaterialWash = chromeSpec.MaterialWash,
                .BodyGlow = chromeSpec.BodyGlow,
                .TopSheen = chromeSpec.TopSheen
            }

        End Function

        Friend Sub DrawButtonChrome(canvas As SKCanvas,
                                     ctx As MASThemeContext,
                                     r As SKRect,
                                     dpi As Single,
                                     contract As MASResolvedComponentContract,
                                     spec As ButtonChromeSpec)

            If _disposed Then Return
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If contract Is Nothing Then Throw New ArgumentNullException(NameOf(contract))
            If r.Width <= 1 OrElse r.Height <= 1 Then Return

            contract.AssertConsumable()

            Dim m As MASSurfaceInteractionRing.Metrics
            Dim baseRect As SKRect

            If Not MASVisualEffectGeometry.TryResolveBaseRect(r, dpi, m, baseRect) Then Return

            Dim radius As Single = ResolveSurfaceRadiusPx(contract, baseRect, dpi)
            radius = PixelSnap.SafeRadius(radius)

            _visualResources.ActionChrome.DrawActionChrome(
                canvas:=canvas,
                ctx:=ctx,
                baseRect:=baseRect,
                radius:=radius,
                dpi:=dpi,
                spec:=New MASActionChromePainter.MASActionChromeSpec With {
                    .FillTop = spec.FillTop,
                    .FillBottom = spec.FillBottom,
                    .BorderOuter = spec.BorderOuter,
                    .BorderInner = spec.BorderInner,
                    .InnerHighlight = spec.InnerHighlight,
                    .InnerShade = spec.InnerShade,
                    .MaterialWash = spec.MaterialWash,
                    .BodyGlow = spec.BodyGlow,
                    .TopSheen = spec.TopSheen
                })

        End Sub

        Friend Sub DrawCardSurface(canvas As SKCanvas,
                                   ctx As MASThemeContext,
                                   r As SKRect,
                                   dpi As Single,
                                   contract As MASResolvedComponentContract,
                                   v As MASCardVisualStyle)

            If _disposed Then Return
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If contract Is Nothing Then Throw New ArgumentNullException(NameOf(contract))
            If r.Width <= 1 OrElse r.Height <= 1 Then Return

            contract.AssertConsumable()

            If contract.SurfaceFamily <> CommonEnums.SurfaceFamily.Card Then

                Return
            End If

            Dim m As MASSurfaceInteractionRing.Metrics
            Dim baseRect As SKRect

            If Not MASVisualEffectGeometry.TryResolveBaseRect(r, dpi, m, baseRect) Then Return

            Dim radius As Single = ResolveSurfaceRadiusPx(contract, baseRect, dpi)
            radius = PixelSnap.SafeRadius(radius)

            Dim frameStrength As MASSurfaceFrameStrength = If(v = MASCardVisualStyle.Secondary,
                                                              MASSurfaceFrameStrength.Level3,
                                                              MASSurfaceFrameStrength.Level4)
            Dim surfaceStrengthLevel As Integer = If(v = MASCardVisualStyle.Secondary, 3, 4)
            Dim borderStrengthLevel As Integer = If(v = MASCardVisualStyle.Secondary, 3, 4)

            Dim surfaceMaterialDrawn As Boolean = MASSurfaceTreatmentRuntimeSurfaceVisual.TryDrawRuntimeSurfaceVisual(
                canvas:=canvas,
                ctx:=ctx,
                boundsPx:=baseRect,
                consumerKind:=MASSurfaceTreatmentConsumerKind.CardSurface,
                materialKey:=MASSurfaceMaterialIds.Auto,
                dpi:=dpi,
                cornerRadiusPx:=radius,
                opacity:=1.0F,
                surfaceRole:=MASSurfaceRole.Card,
                surfaceStrengthLevel:=surfaceStrengthLevel,
                borderStrengthLevel:=borderStrengthLevel,
                requestedFrameStrength:=frameStrength,
                hasExplicitMaterialOverride:=False)

            If surfaceMaterialDrawn Then Return

            _visualResources.ElevatedFill.DrawElevatedSurfaceFill(
                canvas:=canvas,
                ctx:=ctx,
                r:=baseRect,
                radius:=radius,
                dpi:=dpi,
                visualStyle:=v)

            _visualResources.CardFrame.Draw(
                canvas:=canvas,
                ctx:=ctx,
                baseRect:=baseRect,
                radius:=radius,
                dpi:=dpi,
                visualStyle:=v)

        End Sub

        Friend Sub DrawButtonBaseSurface_NoAcrylic(canvas As SKCanvas,
                                                   ctx As MASThemeContext,
                                                   r As SKRect,
                                                   dpi As Single,
                                                   contract As MASResolvedComponentContract)

            If _disposed Then Return
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If contract Is Nothing Then Throw New ArgumentNullException(NameOf(contract))
            If r.Width <= 1 OrElse r.Height <= 1 Then Return

            contract.AssertConsumable()

            Dim app As IMASAppTheme = ctx.Theme
            Dim surfaceTheme As IMASFoundationSurfaceTheme = If(app Is Nothing, Nothing, MASAppThemeContracts.Foundation(app).Surface)

            If surfaceTheme Is Nothing Then Return

            Dim m As MASSurfaceInteractionRing.Metrics
            Dim baseRect As SKRect

            If Not MASVisualEffectGeometry.TryResolveBaseRect(r, dpi, m, baseRect) Then Return

            Dim radius As Single = ResolveSurfaceRadiusPx(contract, baseRect, dpi)
            radius = PixelSnap.SafeRadius(radius)

            Dim topCol As SKColor = surfaceTheme.SurfaceTop
            Dim midCol As SKColor = surfaceTheme.SurfaceMid
            Dim botCol As SKColor = surfaceTheme.SurfaceBot
            Dim wash As SKColor = surfaceTheme.MaterialWash

            Dim behavior As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile =
                MASVisualEffectIntensityProfiles.ResolveAcrylic(contract.SurfaceFamily)

            If behavior.BottomAnchorStrength > 0.0F Then
                botCol = ColorMath.Mix(
                    botCol,
                    ColorMath.TowardBlack(botCol, 0.24F),
                    behavior.BottomAnchorStrength * 0.24F)
            End If

            If behavior.TopBandEmphasis > 0.0F Then
                topCol = ColorMath.Mix(topCol, SKColors.White, behavior.TopBandEmphasis * 0.1F)
                midCol = ColorMath.Mix(midCol, SKColors.White, behavior.TopBandEmphasis * 0.028F)
            End If

            Dim borderOuter As SKColor = surfaceTheme.BorderOuter
            Dim borderInner As SKColor = surfaceTheme.BorderInner

            If borderOuter.Alpha = 0 Then
                borderOuter = ColorMath.WithAlpha(Values.Color.Core.Ink, 52)
            End If

            If borderInner.Alpha = 0 Then
                borderInner = ColorMath.WithAlpha(SKColors.White, 34)
            End If

            _visualResources.CoolAcrylic.DrawCoolAcrylicBody(
                canvas:=canvas,
                baseRect:=baseRect,
                radius:=radius,
                dpi:=dpi,
                fam:=contract.SurfaceFamily,
                topCol:=topCol,
                midCol:=midCol,
                botCol:=botCol,
                wash:=wash,
                borderOuter:=borderOuter,
                borderInner:=borderInner)

        End Sub

        Friend Structure ChipBaseSpec
            Friend Top As SKColor
            Friend Bot As SKColor
            Friend MidT As Single
            Friend TopAlpha As Byte
            Friend MidAlpha As Byte
            Friend BotAlpha As Byte
        End Structure

        Friend Structure ChipFxSpec
            Friend WashColor As SKColor
            Friend WashAlpha As Byte
            Friend InnerGlossColor As SKColor
            Friend InnerGlossAlpha As Byte
            Friend InnerGlossFadeT As Single
            Friend InnerInsetMul As Single
            Friend InnerRadMul As Single
        End Structure

        Friend Sub DrawSegmentedControlChipBaseNoShadow(canvas As SKCanvas,
                                                        r As SKRect,
                                                        dpi As Single,
                                                        contract As MASResolvedComponentContract,
                                                        spec As ChipBaseSpec)

            If _disposed Then Return
            If contract Is Nothing Then Throw New ArgumentNullException(NameOf(contract))

            contract.AssertConsumable()

            Dim radius As Single = ResolveSurfaceRadiusPx(contract, r, dpi)

            _visualResources.Chip.DrawSoftChipChromeBody(
                canvas:=canvas,
                ctx:=Nothing,
                r:=r,
                radius:=radius,
                dpi:=dpi,
                spec:=New MASSoftChipChromePainter.MASSoftChipChromeSpec With {
                    .Top = spec.Top,
                    .Bot = spec.Bot,
                    .MidT = spec.MidT,
                    .TopAlpha = spec.TopAlpha,
                    .MidAlpha = spec.MidAlpha,
                    .BotAlpha = spec.BotAlpha
                })

        End Sub

        Friend Sub DrawChipBaseNoShadow(canvas As SKCanvas,
                                        r As SKRect,
                                        radius As Single,
                                        dpi As Single,
                                        spec As ChipBaseSpec)

            If _disposed Then Return

            _visualResources.Chip.DrawSoftChipChromeBody(
                canvas:=canvas,
                ctx:=Nothing,
                r:=r,
                radius:=radius,
                dpi:=dpi,
                spec:=New MASSoftChipChromePainter.MASSoftChipChromeSpec With {
                    .Top = spec.Top,
                    .Bot = spec.Bot,
                    .MidT = spec.MidT,
                    .TopAlpha = spec.TopAlpha,
                    .MidAlpha = spec.MidAlpha,
                    .BotAlpha = spec.BotAlpha
                })

        End Sub

        Friend Sub DrawChipBaseNoShadow(canvas As SKCanvas,
                                        ctx As MASThemeContext,
                                        r As SKRect,
                                        radius As Single,
                                        dpi As Single,
                                        spec As ChipBaseSpec)

            If _disposed Then Return

            _visualResources.Chip.DrawSoftChipChromeBody(
                canvas:=canvas,
                ctx:=ctx,
                r:=r,
                radius:=radius,
                dpi:=dpi,
                spec:=New MASSoftChipChromePainter.MASSoftChipChromeSpec With {
                    .Top = spec.Top,
                    .Bot = spec.Bot,
                    .MidT = spec.MidT,
                    .TopAlpha = spec.TopAlpha,
                    .MidAlpha = spec.MidAlpha,
                    .BotAlpha = spec.BotAlpha
                })

        End Sub

        Friend Sub DrawChipFxSSOT(canvas As SKCanvas,
                                  r As SKRect,
                                  radius As Single,
                                  dpi As Single,
                                  spec As ChipBaseSpec)

            If _disposed Then Return

            _visualResources.Chip.DrawSoftChipChromeFx(
                canvas:=canvas,
                r:=r,
                radius:=radius,
                dpi:=dpi,
                spec:=New MASSoftChipChromePainter.MASSoftChipChromeSpec With {
                    .Top = spec.Top,
                    .Bot = spec.Bot,
                    .MidT = spec.MidT,
                    .TopAlpha = spec.TopAlpha,
                    .MidAlpha = spec.MidAlpha,
                    .BotAlpha = spec.BotAlpha
                })

        End Sub

        Friend Sub DrawChipFxSSOT(canvas As SKCanvas,
                                  r As SKRect,
                                  radius As Single,
                                  dpi As Single,
                                  spec As ChipBaseSpec,
                                  fxSpec As ChipFxSpec)

            If _disposed Then Return

            _visualResources.Chip.DrawSoftChipChromeFx(
                canvas:=canvas,
                r:=r,
                radius:=radius,
                dpi:=dpi,
                spec:=New MASSoftChipChromePainter.MASSoftChipChromeSpec With {
                    .Top = spec.Top,
                    .Bot = spec.Bot,
                    .MidT = spec.MidT,
                    .TopAlpha = spec.TopAlpha,
                    .MidAlpha = spec.MidAlpha,
                    .BotAlpha = spec.BotAlpha
                },
                fxSpec:=New MASSoftChipChromePainter.MASSoftChipChromeFxSpec With {
                    .WashColor = fxSpec.WashColor,
                    .WashAlpha = fxSpec.WashAlpha,
                    .InnerGlossColor = fxSpec.InnerGlossColor,
                    .InnerGlossAlpha = fxSpec.InnerGlossAlpha,
                    .InnerGlossFadeT = fxSpec.InnerGlossFadeT,
                    .InnerInsetMul = fxSpec.InnerInsetMul,
                    .InnerRadMul = fxSpec.InnerRadMul
                })

        End Sub

        Friend Structure BarChromeFxSpec
            Friend TopLift As SKColor
            Friend Sheen As SKColor
            Friend Base As SKColor
            Friend BottomShade As SKColor
            Friend InnerHighlightBase As SKColor
            Friend InnerShadowBase As SKColor
            Friend ShadowBase As SKColor
            Friend BulgeAlpha As Byte
            Friend SpecularAlpha As Byte
            Friend ShadowAlpha As Byte
            Friend SpecularBandHDip As Single
            Friend SpecularTopPadDip As Single
            Friend ShadowDyDip As Single
            Friend ShadowSigmaDip As Single
            Friend ShadowCasterHDip As Single
        End Structure

        Friend Sub DrawBarChromeFx(canvas As SKCanvas,
                                    r As SKRect,
                                    dpi As Single,
                                    contract As MASResolvedComponentContract,
                                    spec As BarChromeFxSpec,
                                    Optional radiusOverridePx As Single = -1.0F)

            If _disposed Then Return
            If canvas Is Nothing Then Return
            If contract Is Nothing Then Throw New ArgumentNullException(NameOf(contract))
            If r.Width <= 1 OrElse r.Height <= 1 Then Return

            contract.AssertConsumable()

            Dim m As MASSurfaceInteractionRing.Metrics
            Dim baseRect As SKRect

            If Not MASVisualEffectGeometry.TryResolveBaseRect(r, dpi, m, baseRect) Then Return

            Dim radiusPx As Single

            If radiusOverridePx >= 0.0F Then
                radiusPx = PixelSnap.SafeRadius(radiusOverridePx)
            Else
                radiusPx = ResolveSurfaceRadiusPx(contract, baseRect, dpi)
            End If

            _visualResources.ActionChrome.DrawBarChromeFx(
                canvas:=canvas,
                r:=baseRect,
                radiusPx:=radiusPx,
                dpi:=dpi,
                spec:=New MASActionChromePainter.MASBarChromeFxSpec With {
                    .TopLift = spec.TopLift,
                    .Sheen = spec.Sheen,
                    .Base = spec.Base,
                    .BottomShade = spec.BottomShade,
                    .InnerHighlightBase = spec.InnerHighlightBase,
                    .InnerShadowBase = spec.InnerShadowBase,
                    .ShadowBase = spec.ShadowBase,
                    .BulgeAlpha = spec.BulgeAlpha,
                    .SpecularAlpha = spec.SpecularAlpha,
                    .ShadowAlpha = spec.ShadowAlpha,
                    .SpecularBandHDip = spec.SpecularBandHDip,
                    .SpecularTopPadDip = spec.SpecularTopPadDip,
                    .ShadowDyDip = spec.ShadowDyDip,
                    .ShadowSigmaDip = spec.ShadowSigmaDip,
                    .ShadowCasterHDip = spec.ShadowCasterHDip
                })

        End Sub

        Friend Shared Function BuildChipBaseSpec(appTheme As IMASAppTheme,
                                                 surfaceTheme As IMASFoundationSurfaceTheme,
                                                 Optional midT As Single = 0.55F,
                                                 Optional topA As Byte = 165,
                                                 Optional midA As Byte = 145,
                                                 Optional botA As Byte = 165) As ChipBaseSpec

            Dim spec As MASSoftChipChromePainter.MASSoftChipChromeSpec =
                MASSoftChipChromePainter.BuildSoftChipChromeSpec(appTheme, surfaceTheme, midT, topA, midA, botA)

            Return New ChipBaseSpec With {
                .Top = spec.Top,
                .Bot = spec.Bot,
                .MidT = spec.MidT,
                .TopAlpha = spec.TopAlpha,
                .MidAlpha = spec.MidAlpha,
                .BotAlpha = spec.BotAlpha
            }

        End Function

        Friend Shared Function BuildChipBaseSpec(top As SKColor,
                                                 bot As SKColor,
                                                 midT As Single,
                                                 topA As Byte,
                                                 midA As Byte,
                                                 botA As Byte) As MASVisualPrimitivesPainter.ChipBaseSpec

            Dim spec As MASSoftChipChromePainter.MASSoftChipChromeSpec =
                MASSoftChipChromePainter.BuildSoftChipChromeSpec(top, bot, midT, topA, midA, botA)

            Return New MASVisualPrimitivesPainter.ChipBaseSpec With {
                .Top = spec.Top,
                .Bot = spec.Bot,
                .MidT = spec.MidT,
                .TopAlpha = spec.TopAlpha,
                .MidAlpha = spec.MidAlpha,
                .BotAlpha = spec.BotAlpha
            }

        End Function

#End Region



    End Class

End Namespace
