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 shared media glyphs. It is isolated from labels, surfaces, and element actions.
    ''' </summary>
    Friend NotInheritable Class MASMediaButtonGlyphPainter

        Private Sub New()
        End Sub

        Friend Shared Sub Draw(canvas As SKCanvas,
                               glyphKind As MASMediaButtonGlyphKind,
                               rect As SKRect,
                               dpi As Single,
                               color As SKColor)
            If canvas Is Nothing Then Return
            If rect.Width <= 1.0F OrElse rect.Height <= 1.0F Then Return

            Select Case glyphKind
                Case MASMediaButtonGlyphKind.ZoomIn
                    DrawZoomGlyph(canvas, rect, dpi, color, True)
                Case MASMediaButtonGlyphKind.ZoomOut
                    DrawZoomGlyph(canvas, rect, dpi, color, False)
                Case MASMediaButtonGlyphKind.Fit
                    DrawFitGlyph(canvas, rect, dpi, color)
                Case MASMediaButtonGlyphKind.Actual
                    DrawActualSizeGlyph(canvas, rect, dpi, color)
                Case MASMediaButtonGlyphKind.RotateLeft
                    DrawRotateGlyph(canvas, rect, dpi, color, False)
                Case MASMediaButtonGlyphKind.RotateRight
                    DrawRotateGlyph(canvas, rect, dpi, color, True)
                Case MASMediaButtonGlyphKind.Export
                    DrawExportGlyph(canvas, rect, dpi, color)
                Case MASMediaButtonGlyphKind.Reset
                    DrawResetGlyph(canvas, rect, dpi, color)
                Case MASMediaButtonGlyphKind.FlipHorizontal
                    DrawFlipGlyph(canvas, rect, dpi, color, vertical:=False)
                Case MASMediaButtonGlyphKind.FlipVertical
                    DrawFlipGlyph(canvas, rect, dpi, color, vertical:=True)
            End Select
        End Sub

        Private Shared Function CreateIconStroke(dpi As Single,
                                                 color As SKColor,
                                                 Optional thicknessDip As Single = 1.68F) As SKPaint
            Return New SKPaint With {
                .IsAntialias = True,
                .IsDither = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(1.35F, thicknessDip * PixelSnap.SafeDpi(dpi)),
                .Color = color,
                .StrokeCap = SKStrokeCap.Round,
                .StrokeJoin = SKStrokeJoin.Round
            }
        End Function

        Private Shared Sub DrawZoomGlyph(canvas As SKCanvas,
                                         rect As SKRect,
                                         dpi As Single,
                                         color As SKColor,
                                         plus As Boolean)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Using p As SKPaint = CreateIconStroke(safeDpi, color, 1.68F)
                Dim cx As Single = rect.Left + rect.Width * 0.43F
                Dim cy As Single = rect.Top + rect.Height * 0.40F
                Dim r As Single = Math.Min(rect.Width, rect.Height) * 0.25F
                canvas.DrawCircle(cx, cy, r, p)

                Dim handleStartX As Single = cx + r * 0.68F
                Dim handleStartY As Single = cy + r * 0.68F
                canvas.DrawLine(handleStartX,
                                handleStartY,
                                rect.Right - rect.Width * 0.14F,
                                rect.Bottom - rect.Height * 0.14F,
                                p)

                Dim arm As Single = Math.Max(4.8F * safeDpi, r * 0.54F)
                canvas.DrawLine(cx - arm, cy, cx + arm, cy, p)
                If plus Then
                    canvas.DrawLine(cx, cy - arm, cx, cy + arm, p)
                End If
            End Using
        End Sub

        Private Shared Sub DrawFitGlyph(canvas As SKCanvas,
                                        rect As SKRect,
                                        dpi As Single,
                                        color As SKColor)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Using p As SKPaint = CreateIconStroke(safeDpi, color, 1.68F)
                Dim inset As Single = rect.Width * 0.18F
                Dim len As Single = rect.Width * 0.205F
                Dim left As Single = rect.Left + inset
                Dim right As Single = rect.Right - inset
                Dim top As Single = rect.Top + inset
                Dim bottom As Single = rect.Bottom - inset

                canvas.DrawLine(left, top, left + len, top, p)
                canvas.DrawLine(left, top, left, top + len, p)
                canvas.DrawLine(right, top, right - len, top, p)
                canvas.DrawLine(right, top, right, top + len, p)
                canvas.DrawLine(left, bottom, left + len, bottom, p)
                canvas.DrawLine(left, bottom, left, bottom - len, p)
                canvas.DrawLine(right, bottom, right - len, bottom, p)
                canvas.DrawLine(right, bottom, right, bottom - len, p)
            End Using
        End Sub


        Private Shared Sub DrawActualSizeGlyph(canvas As SKCanvas,
                                               rect As SKRect,
                                               dpi As Single,
                                               color As SKColor)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Using p As SKPaint = CreateIconStroke(safeDpi, color, 1.62F)
                Dim boxInset As Single = rect.Width * 0.18F
                Dim box As New SKRect(rect.Left + boxInset,
                                      rect.Top + boxInset,
                                      rect.Right - boxInset,
                                      rect.Bottom - boxInset)
                Dim radius As Single = Math.Max(2.0F * safeDpi, rect.Width * 0.06F)
                canvas.DrawRoundRect(box, radius, radius, p)

                Dim tick As Single = Math.Max(3.8F * safeDpi, rect.Width * 0.12F)
                canvas.DrawLine(box.Left, box.Top + tick, box.Left + tick, box.Top, p)
                canvas.DrawLine(box.Right - tick, box.Bottom, box.Right, box.Bottom - tick, p)

                Using textPaint As New SKPaint With {
                    .IsAntialias = True,
                    .SubpixelText = True,
                    .TextAlign = SKTextAlign.Center,
                    .TextSize = Math.Max(8.0F * safeDpi, rect.Height * 0.23F),
                    .Color = color,
                    .FakeBoldText = True
                }
                    Dim fm As SKFontMetrics = textPaint.FontMetrics
                    Dim baseline As Single = box.MidY - (fm.Ascent + fm.Descent) * 0.5F
                    canvas.DrawText("1:1", box.MidX, baseline, textPaint)
                End Using
            End Using
        End Sub

        Private Shared Sub DrawRotateGlyph(canvas As SKCanvas,
                                           rect As SKRect,
                                           dpi As Single,
                                           color As SKColor,
                                           clockwise As Boolean)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Using p As SKPaint = CreateIconStroke(safeDpi, color, 1.68F)
                Dim inset As Single = rect.Width * 0.19F
                Dim oval As New SKRect(rect.Left + inset,
                                       rect.Top + inset,
                                       rect.Right - inset,
                                       rect.Bottom - inset)

                If clockwise Then
                    canvas.DrawArc(oval, 208.0F, 285.0F, False, p)
                    Dim tip As New SKPoint(oval.Right - oval.Width * 0.02F, oval.Top + oval.Height * 0.33F)
                    Dim a As Single = Math.Max(5.0F * safeDpi, rect.Width * 0.13F)
                    canvas.DrawLine(tip.X, tip.Y, tip.X - a * 0.95F, tip.Y - a * 0.12F, p)
                    canvas.DrawLine(tip.X, tip.Y, tip.X - a * 0.25F, tip.Y + a * 0.9F, p)
                Else
                    canvas.DrawArc(oval, -28.0F, -285.0F, False, p)
                    Dim tip As New SKPoint(oval.Left + oval.Width * 0.02F, oval.Top + oval.Height * 0.33F)
                    Dim a As Single = Math.Max(5.0F * safeDpi, rect.Width * 0.13F)
                    canvas.DrawLine(tip.X, tip.Y, tip.X + a * 0.95F, tip.Y - a * 0.12F, p)
                    canvas.DrawLine(tip.X, tip.Y, tip.X + a * 0.25F, tip.Y + a * 0.9F, p)
                End If
            End Using
        End Sub

        Private Shared Sub DrawExportGlyph(canvas As SKCanvas,
                                           rect As SKRect,
                                           dpi As Single,
                                           color As SKColor)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Using p As SKPaint = CreateIconStroke(safeDpi, color, 1.68F)
                Dim cx As Single = rect.MidX
                Dim top As Single = rect.Top + rect.Height * 0.13F
                Dim trayTop As Single = rect.Top + rect.Height * 0.64F
                Dim trayBottom As Single = rect.Bottom - rect.Height * 0.12F
                Dim left As Single = rect.Left + rect.Width * 0.19F
                Dim right As Single = rect.Right - rect.Width * 0.19F
                Dim arrow As Single = Math.Max(5.0F * safeDpi, rect.Width * 0.18F)

                canvas.DrawLine(cx, trayTop, cx, top, p)
                canvas.DrawLine(cx, top, cx - arrow, top + arrow, p)
                canvas.DrawLine(cx, top, cx + arrow, top + arrow, p)

                canvas.DrawLine(left, trayTop, left, trayBottom, p)
                canvas.DrawLine(left, trayBottom, right, trayBottom, p)
                canvas.DrawLine(right, trayBottom, right, trayTop, p)
            End Using
        End Sub

        Private Shared Sub DrawResetGlyph(canvas As SKCanvas,
                                          rect As SKRect,
                                          dpi As Single,
                                          color As SKColor)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Using p As SKPaint = CreateIconStroke(safeDpi, color, 1.68F)
                Dim inset As Single = rect.Width * 0.18F
                Dim oval As New SKRect(rect.Left + inset,
                                       rect.Top + inset,
                                       rect.Right - inset,
                                       rect.Bottom - inset)
                canvas.DrawArc(oval, 205.0F, 310.0F, False, p)

                Dim tip As New SKPoint(oval.Right - oval.Width * 0.05F, oval.Top + oval.Height * 0.25F)
                Dim a As Single = Math.Max(4.8F * safeDpi, rect.Width * 0.125F)
                canvas.DrawLine(tip.X, tip.Y, tip.X - a * 0.85F, tip.Y - a * 0.08F, p)
                canvas.DrawLine(tip.X, tip.Y, tip.X - a * 0.18F, tip.Y + a * 0.88F, p)
            End Using
        End Sub

        Private Shared Sub DrawFlipGlyph(canvas As SKCanvas,
                                         rect As SKRect,
                                         dpi As Single,
                                         color As SKColor,
                                         vertical As Boolean)
            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Dim strokeWidth As Single = Math.Max(1.35F, 1.68F * safeDpi)
            Dim cx As Single = rect.MidX
            Dim cy As Single = rect.MidY
            Dim top As Single = rect.Top + rect.Height * 0.15F
            Dim bottom As Single = rect.Bottom - rect.Height * 0.15F
            Dim left As Single = rect.Left + rect.Width * 0.12F
            Dim right As Single = rect.Right - rect.Width * 0.12F
            Dim arrow As Single = Math.Max(4.4F * safeDpi, rect.Width * 0.132F)

            Using p As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = strokeWidth,
                .Color = color,
                .StrokeCap = SKStrokeCap.Round,
                .StrokeJoin = SKStrokeJoin.Round
            }
                If vertical Then
                    canvas.DrawLine(left, cy, right, cy, p)
                    canvas.DrawLine(cx, top, cx, cy - arrow * 0.45F, p)
                    canvas.DrawLine(cx - arrow, top + arrow, cx, top, p)
                    canvas.DrawLine(cx + arrow, top + arrow, cx, top, p)

                    canvas.DrawLine(cx, cy + arrow * 0.45F, cx, bottom, p)
                    canvas.DrawLine(cx - arrow, bottom - arrow, cx, bottom, p)
                    canvas.DrawLine(cx + arrow, bottom - arrow, cx, bottom, p)
                Else
                    canvas.DrawLine(cx, top, cx, bottom, p)
                    canvas.DrawLine(left, cy, cx - arrow * 0.45F, cy, p)
                    canvas.DrawLine(left + arrow, cy - arrow, left, cy, p)
                    canvas.DrawLine(left + arrow, cy + arrow, left, cy, p)

                    canvas.DrawLine(cx + arrow * 0.45F, cy, right, cy, p)
                    canvas.DrawLine(right - arrow, cy - arrow, right, cy, p)
                    canvas.DrawLine(right - arrow, cy + arrow, right, cy, p)
                End If
            End Using
        End Sub

    End Class

End Namespace
