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

    ' <summary>
    ' Premium enhancement layers for MASAcrylicEffectPainter.
    ' Kept apart from the base layer pass so acrylic recipe tuning is easier to audit visually.
    ' </summary>
    Partial Friend NotInheritable Class MASAcrylicEffectPainter

#Region "Extended premium acrylic layers"

        Private Shared Function ResolveTopGlossAlpha(baseAlpha As Byte,
                                                     intensity As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile) As Byte

            Dim mul As Single =
                0.68F +
                intensity.SheenStrength * 0.34F +
                intensity.TopBandEmphasis * 0.08F

            Return CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(baseAlpha * mul)))))

        End Function

        Private Sub DrawCoolAcrylicTopGlossBand(canvas As SKCanvas,
                                                r As SKRect,
                                                radiusPx As Single,
                                                dpi As Single,
                                                midCol As SKColor,
                                                wash As SKColor,
                                                topGlossAlpha As Byte,
                                                intensity As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile)

            If topGlossAlpha = 0 Then Return
            If intensity.SheenStrength <= 0.0F Then Return

            Dim hBase As Single =
                Math.Min(
                    r.Height * SurfaceTokens.AcrylicShineHeightRatio,
                    36.0F * dpi)

            Dim h As Single =
                hBase * (0.94F + (intensity.SheenHeightMul - 1.0F) * 0.72F)

            If h <= 1.0F Then Return

            Dim band As New SKRect(r.Left, r.Top, r.Right, r.Top + h)

            Dim hi1 As SKColor =
                ColorMath.WithAlpha(
                    ColorMath.Mix(wash, midCol, 0.28F + intensity.TopBandEmphasis * 0.04F),
                    topGlossAlpha)

            Dim hi2 As SKColor =
                ColorMath.WithAlpha(
                    ColorMath.Mix(midCol, wash, 0.12F + intensity.TopBandEmphasis * 0.03F),
                    CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(topGlossAlpha * 0.52F))))))

            MASVisualPrimitivesPainter.WithClipRoundRect(canvas, r, radiusPx,
                Sub()
                    Using sh As SKShader = SKShader.CreateLinearGradient(
                        New SKPoint(band.Left, band.Top),
                        New SKPoint(band.Left, band.Bottom),
                        New SKColor() {hi1, hi2, SKColors.Transparent},
                        New Single() {0.0F, 0.24F, 1.0F},
                        SKShaderTileMode.Clamp)

                        _fill.Shader = sh
                        _fill.Color = SKColors.White
                        _fill.BlendMode = SKBlendMode.Screen
                        canvas.DrawRect(band, _fill)
                        _fill.Shader = Nothing
                        _fill.BlendMode = SKBlendMode.SrcOver
                    End Using
                End Sub)

        End Sub

        Private Sub DrawCoolAcrylicEdgeFade(canvas As SKCanvas,
                                            r As SKRect,
                                            radiusPx As Single,
                                            dpi As Single,
                                            midCol As SKColor,
                                            wash As SKColor,
                                            edgeFadeAlpha As Byte,
                                            edgeFadeSizeDip As Single,
                                            edgeFadeTopBoost As Byte)

            Dim fade As Single = edgeFadeSizeDip * dpi
            If fade <= 1.0F Then Return
            If fade * 2.0F >= r.Width OrElse fade * 2.0F >= r.Height Then Return

            Dim a As Integer = CInt(edgeFadeAlpha)
            If a <= 0 Then Return

            Dim aMain As Integer = Math.Max(0, Math.Min(255, a))
            Dim aTop As Integer = Math.Max(0, Math.Min(255, CInt(a + edgeFadeTopBoost)))
            Dim aBot As Integer = Math.Max(0, Math.Min(255, Math.Max(0, a - 8)))

            Dim hiBase As SKColor = ColorMath.Mix(midCol, wash, 0.18F)

            MASVisualPrimitivesPainter.WithClipRoundRect(canvas, r, radiusPx,
                Sub()
                    _fill.Shader = Nothing
                    _fill.BlendMode = SKBlendMode.Screen
                    _fill.Color = SKColors.White

                    Using shL As SKShader = SKShader.CreateLinearGradient(
                        New SKPoint(r.Left, r.Top),
                        New SKPoint(r.Left + fade, r.Top),
                        New SKColor() {
                            ColorMath.WithAlpha(hiBase, CByte(aMain)),
                            SKColors.Transparent
                        },
                        New Single() {0.0F, 1.0F},
                        SKShaderTileMode.Clamp)

                        _fill.Shader = shL
                        canvas.DrawRect(New SKRect(r.Left, r.Top, r.Left + fade, r.Bottom), _fill)
                        _fill.Shader = Nothing
                    End Using

                    Using shR As SKShader = SKShader.CreateLinearGradient(
                        New SKPoint(r.Right - fade, r.Top),
                        New SKPoint(r.Right, r.Top),
                        New SKColor() {
                            SKColors.Transparent,
                            ColorMath.WithAlpha(hiBase, CByte(aMain))
                        },
                        New Single() {0.0F, 1.0F},
                        SKShaderTileMode.Clamp)

                        _fill.Shader = shR
                        canvas.DrawRect(New SKRect(r.Right - fade, r.Top, r.Right, r.Bottom), _fill)
                        _fill.Shader = Nothing
                    End Using

                    Using shT As SKShader = SKShader.CreateLinearGradient(
                        New SKPoint(r.Left, r.Top),
                        New SKPoint(r.Left, r.Top + fade),
                        New SKColor() {
                            ColorMath.WithAlpha(hiBase, CByte(aTop)),
                            SKColors.Transparent
                        },
                        New Single() {0.0F, 1.0F},
                        SKShaderTileMode.Clamp)

                        _fill.Shader = shT
                        canvas.DrawRect(New SKRect(r.Left, r.Top, r.Right, r.Top + fade), _fill)
                        _fill.Shader = Nothing
                    End Using

                    If aBot > 0 Then
                        Using shB As SKShader = SKShader.CreateLinearGradient(
                            New SKPoint(r.Left, r.Bottom - fade),
                            New SKPoint(r.Left, r.Bottom),
                            New SKColor() {
                                SKColors.Transparent,
                                ColorMath.WithAlpha(hiBase, CByte(aBot))
                            },
                            New Single() {0.0F, 1.0F},
                            SKShaderTileMode.Clamp)

                            _fill.Shader = shB
                            canvas.DrawRect(New SKRect(r.Left, r.Bottom - fade, r.Right, r.Bottom), _fill)
                            _fill.Shader = Nothing
                        End Using
                    End If

                    _fill.BlendMode = SKBlendMode.SrcOver
                End Sub)

        End Sub

        Private Sub DrawCoolAcrylicBottomInnerShade(canvas As SKCanvas,
                                                    r As SKRect,
                                                    radiusPx As Single,
                                                    dpi As Single,
                                                    midCol As SKColor,
                                                    innerShadeBottomAlpha As Byte,
                                                    intensity As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile)

            If innerShadeBottomAlpha = 0 Then Return

            Dim effectiveAlpha As Byte =
                CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(innerShadeBottomAlpha * (0.58F + intensity.BottomAnchorStrength * 0.34F))))))

            If effectiveAlpha = 0 Then Return

            Dim shadeCol As SKColor =
                ColorMath.WithAlpha(
                    ColorMath.TowardBlack(midCol, 0.24F),
                    effectiveAlpha)

            MASVisualPrimitivesPainter.WithClipRoundRect(canvas, r, radiusPx,
                Sub()
                    Using sh As SKShader = SKShader.CreateLinearGradient(
                        New SKPoint(r.Left, r.Top),
                        New SKPoint(r.Left, r.Bottom),
                        New SKColor() {SKColors.Transparent, shadeCol},
                        New Single() {0.95F, 1.0F},
                        SKShaderTileMode.Clamp)

                        _fill.Shader = sh
                        _fill.Color = SKColors.White
                        _fill.BlendMode = SKBlendMode.Multiply
                        canvas.DrawRect(r, _fill)
                        _fill.Shader = Nothing
                        _fill.BlendMode = SKBlendMode.SrcOver
                    End Using
                End Sub)

        End Sub

        Private Sub DrawCoolAcrylicGrain(canvas As SKCanvas,
                                         r As SKRect,
                                         radiusPx As Single,
                                         dpi As Single,
                                         grainAlpha As Byte,
                                         grainTileDip As Single)

            If grainAlpha = 0 Then Return

            EnsureGrainCache(dpi, grainTileDip)
            If _grainShader Is Nothing Then Return

            MASVisualPrimitivesPainter.WithClipRoundRect(canvas, r, radiusPx,
                Sub()
                    _fill.Shader = _grainShader
                    _fill.Color = New SKColor(255, 255, 255, grainAlpha)
                    _fill.BlendMode = SKBlendMode.SoftLight
                    canvas.DrawRect(r, _fill)
                    _fill.Shader = Nothing
                    _fill.BlendMode = SKBlendMode.SrcOver
                End Sub)

        End Sub

        Private Sub DrawCoolAcrylicRims(canvas As SKCanvas,
                                        r As SKRect,
                                        radiusPx As Single,
                                        dpi As Single,
                                        midCol As SKColor,
                                        borderOuter As SKColor,
                                        borderInner As SKColor,
                                        strokeW As Single,
                                        innerRimAlpha As Byte,
                                        intensity As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile)

            Dim outerCol As SKColor = borderOuter

            If outerCol.Alpha = 0 Then
                outerCol = ColorMath.WithAlpha(ColorMath.TowardBlack(midCol, 0.28F), 88)
            End If

            Dim outerMul As Single =
                0.62F + intensity.OuterBorderStrength * 0.38F

            outerCol = ColorMath.WithAlpha(
                outerCol,
                CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(outerCol.Alpha * outerMul))))))

            Dim save As Integer = canvas.Save()

            Try
                Dim outerStroke As MASVisualPrimitivesPainter.StrokeRoundRectInfo =
                    MASVisualPrimitivesPainter.BuildStrokeRoundRectInfo(
                        baseRect:=r,
                        baseRadius:=radiusPx,
                        dpi:=dpi,
                        edgeInsetPx:=0.0F,
                        strokeWidthPx:=strokeW)

                If outerStroke.HasValue Then
                    _hairline.StrokeWidth = outerStroke.StrokeWidth
                    _hairline.IsAntialias = True
                    _hairline.Color = outerCol
                    canvas.DrawRoundRect(outerStroke.Rect, outerStroke.Radius, outerStroke.Radius, _hairline)
                End If

                If innerRimAlpha > 0 Then
                    Dim innerStroke As MASVisualPrimitivesPainter.StrokeRoundRectInfo =
                        MASVisualPrimitivesPainter.BuildStrokeRoundRectInfo(
                            baseRect:=r,
                            baseRadius:=radiusPx,
                            dpi:=dpi,
                            edgeInsetPx:=Math.Max(SurfaceTokens.FxRingInset * dpi, SurfaceTokens.FxRingMinStrokePx),
                            strokeWidthPx:=Math.Max(SurfaceTokens.FxRingStroke * dpi, SurfaceTokens.FxRingMinStrokePx))

                    If innerStroke.HasValue Then
                        Dim resolvedInner As SKColor = borderInner

                        Dim innerMul As Single =
                            0.56F + intensity.InnerBorderStrength * 0.34F

                        If resolvedInner.Alpha = 0 Then
                            resolvedInner = New SKColor(
                                255,
                                255,
                                255,
                                CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(innerRimAlpha * innerMul))))))
                        Else
                            resolvedInner = ColorMath.WithAlpha(
                                resolvedInner,
                                CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(innerRimAlpha * innerMul))))))
                        End If

                        _hairline.StrokeWidth = innerStroke.StrokeWidth
                        _hairline.Color = resolvedInner
                        canvas.DrawRoundRect(innerStroke.Rect, innerStroke.Radius, innerStroke.Radius, _hairline)
                    End If
                End If

            Finally
                canvas.RestoreToCount(save)
            End Try

        End Sub

        Friend Sub DrawCoolAcrylicTopEdgeHighlight(canvas As SKCanvas,
                                                   r As SKRect,
                                                   radiusPx As Single,
                                                   dpi As Single,
                                                   midCol As SKColor)

            If _disposed Then Return
            If canvas Is Nothing Then Return
            If r.Width <= 1 OrElse r.Height <= 1 Then Return

            Dim h As Single = Math.Min(8.0F * dpi, r.Height * 0.22F)
            If h <= 1.0F Then Return

            Const hiA As Byte = 30

            Dim hi As SKColor =
                ColorMath.WithAlpha(ColorMath.Mix(SKColors.White, midCol, 0.08F), hiA)

            MASVisualPrimitivesPainter.WithClipRoundRect(canvas, r, radiusPx,
                Sub()
                    Using sh As SKShader = SKShader.CreateLinearGradient(
                        New SKPoint(r.Left, r.Top),
                        New SKPoint(r.Left, r.Top + h),
                        New SKColor() {hi, SKColors.Transparent},
                        New Single() {0.0F, 1.0F},
                        SKShaderTileMode.Clamp)

                        _fill.Shader = sh
                        _fill.Color = SKColors.White
                        _fill.BlendMode = SKBlendMode.Screen
                        canvas.DrawRect(New SKRect(r.Left, r.Top, r.Right, r.Top + h), _fill)
                        _fill.BlendMode = SKBlendMode.SrcOver
                        _fill.Shader = Nothing
                    End Using
                End Sub)

        End Sub

#End Region

    

    End Class

End Namespace
