Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.General
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Draws only the physical button surface: shadow, body, rim, border, and highlight.
    ''' </summary>
    Friend NotInheritable Class MASMediaButtonSurfacePainter

        Private Sub New()
        End Sub

        Friend Shared Sub Draw(canvas As SKCanvas,
                               rect As SKRect,
                               radius As Single,
                               dpi As Single,
                               palette As MASMediaButtonPalette)
            If canvas Is Nothing Then Return
            If rect.Width <= 1.0F OrElse rect.Height <= 1.0F Then Return

            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            DrawSoftElevation(canvas, rect, radius, safeDpi, palette)
            DrawBody(canvas, rect, radius, palette)
            DrawBottomShade(canvas, rect, radius, safeDpi, palette)
            DrawSideRim(canvas, rect, radius, safeDpi, palette)
            DrawBorder(canvas, rect, radius, safeDpi, palette)
            DrawTopHighlight(canvas, rect, radius, safeDpi, palette)
        End Sub

        Private Shared Sub DrawSoftElevation(canvas As SKCanvas,
                                             rect As SKRect,
                                             radius As Single,
                                             dpi As Single,
                                             palette As MASMediaButtonPalette)
            If palette.Shadow.Alpha = 0 Then Return

            Dim shadowRect As New SKRect(rect.Left,
                                         rect.Top + (1.1F * dpi),
                                         rect.Right,
                                         rect.Bottom + (2.2F * dpi))
            MASShadowPainter.DrawImmediateBlurredRoundRectShadow(
                canvas:=canvas,
                rectPx:=shadowRect,
                radiusPx:=radius,
                sigmaPx:=3.6F * dpi,
                color:=palette.Shadow)
        End Sub

        Private Shared Sub DrawBody(canvas As SKCanvas,
                                    rect As SKRect,
                                    radius As Single,
                                    palette As MASMediaButtonPalette)
            Using shader As SKShader = SKShader.CreateLinearGradient(
                New SKPoint(rect.MidX, rect.Top),
                New SKPoint(rect.MidX, rect.Bottom),
                New SKColor() {palette.TopFill, palette.BottomFill},
                New Single() {0.0F, 1.0F},
                SKShaderTileMode.Clamp)
                Using fill As New SKPaint With {
                    .IsAntialias = True,
                    .IsDither = True,
                    .Style = SKPaintStyle.Fill,
                    .Shader = shader
                }
                    canvas.DrawRoundRect(rect, radius, radius, fill)
                End Using
            End Using
        End Sub

        Private Shared Sub DrawBottomShade(canvas As SKCanvas,
                                           rect As SKRect,
                                           radius As Single,
                                           dpi As Single,
                                           palette As MASMediaButtonPalette)
            If palette.BottomShade.Alpha = 0 Then Return

            Dim shadeRect As New SKRect(rect.Left + 1.5F * dpi,
                                        rect.Top + rect.Height * 0.62F,
                                        rect.Right - 1.5F * dpi,
                                        rect.Bottom - 1.0F * dpi)
            If shadeRect.Width <= 1.0F OrElse shadeRect.Height <= 1.0F Then Return

            Using clip As New SKPath()
                clip.AddRoundRect(rect, radius, radius)
                canvas.Save()
                canvas.ClipPath(clip, SKClipOperation.Intersect, True)

                Using shader As SKShader = SKShader.CreateLinearGradient(
                    New SKPoint(shadeRect.MidX, shadeRect.Top),
                    New SKPoint(shadeRect.MidX, shadeRect.Bottom),
                    New SKColor() {ColorMath.WithAlpha(palette.BottomShade, 0), palette.BottomShade},
                    New Single() {0.0F, 1.0F},
                    SKShaderTileMode.Clamp)
                    Using p As New SKPaint With {
                        .IsAntialias = True,
                        .IsDither = True,
                        .Style = SKPaintStyle.Fill,
                        .Shader = shader
                    }
                        canvas.DrawRoundRect(shadeRect,
                                             Math.Max(1.0F, radius - 2.0F * dpi),
                                             Math.Max(1.0F, radius - 2.0F * dpi),
                                             p)
                    End Using
                End Using

                canvas.Restore()
            End Using
        End Sub

        Private Shared Sub DrawSideRim(canvas As SKCanvas,
                                       rect As SKRect,
                                       radius As Single,
                                       dpi As Single,
                                       palette As MASMediaButtonPalette)
            If palette.SideRim.Alpha = 0 Then Return

            Dim rimRect As SKRect = PixelSnap.InsetAll(rect, 1.2F * dpi)
            If rimRect.Width <= 1.0F OrElse rimRect.Height <= 1.0F Then Return

            Using p As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(0.50F, 0.64F * dpi),
                .Color = palette.SideRim
            }
                canvas.DrawRoundRect(rimRect,
                                     Math.Max(1.0F, radius - 1.2F * dpi),
                                     Math.Max(1.0F, radius - 1.2F * dpi),
                                     p)
            End Using
        End Sub

        Private Shared Sub DrawBorder(canvas As SKCanvas,
                                      rect As SKRect,
                                      radius As Single,
                                      dpi As Single,
                                      palette As MASMediaButtonPalette)
            Dim borderRect As SKRect = PixelSnap.InsetAll(rect, 0.5F * dpi)
            Using stroke As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(0.65F, 0.88F * dpi),
                .Color = palette.Stroke
            }
                canvas.DrawRoundRect(borderRect,
                                     Math.Max(1.0F, radius - 0.5F * dpi),
                                     Math.Max(1.0F, radius - 0.5F * dpi),
                                     stroke)
            End Using

            Dim innerRect As SKRect = PixelSnap.InsetAll(rect, 1.35F * dpi)
            Using innerStroke As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(0.50F, 0.64F * dpi),
                .Color = palette.InnerStroke
            }
                canvas.DrawRoundRect(innerRect,
                                     Math.Max(1.0F, radius - 1.35F * dpi),
                                     Math.Max(1.0F, radius - 1.35F * dpi),
                                     innerStroke)
            End Using
        End Sub

        Private Shared Sub DrawTopHighlight(canvas As SKCanvas,
                                            rect As SKRect,
                                            radius As Single,
                                            dpi As Single,
                                            palette As MASMediaButtonPalette)
            If palette.Highlight.Alpha = 0 Then Return

            Dim highlightRect As New SKRect(rect.Left + (4.8F * dpi),
                                            rect.Top + (3.8F * dpi),
                                            rect.Right - (4.8F * dpi),
                                            rect.Top + Math.Max(11.0F * dpi, rect.Height * 0.34F))
            If highlightRect.Width <= 1.0F OrElse highlightRect.Height <= 1.0F Then Return

            Using clip As New SKPath()
                clip.AddRoundRect(rect, radius, radius)
                canvas.Save()
                canvas.ClipPath(clip, SKClipOperation.Intersect, True)

                Using shader As SKShader = SKShader.CreateLinearGradient(
                    New SKPoint(highlightRect.MidX, highlightRect.Top),
                    New SKPoint(highlightRect.MidX, highlightRect.Bottom),
                    New SKColor() {palette.Highlight, ColorMath.WithAlpha(palette.Highlight, 0)},
                    New Single() {0.0F, 1.0F},
                    SKShaderTileMode.Clamp)
                    Using p As New SKPaint With {
                        .IsAntialias = True,
                        .IsDither = True,
                        .Style = SKPaintStyle.Fill,
                        .Shader = shader
                    }
                        canvas.DrawRoundRect(highlightRect,
                                             Math.Max(1.0F, radius - 3.0F * dpi),
                                             Math.Max(1.0F, radius - 3.0F * dpi),
                                             p)
                    End Using
                End Using

                canvas.Restore()
            End Using
        End Sub

    End Class

End Namespace
