Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Components
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Icons
Imports Nexamas.UI.Theming
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Values
Imports Nexamas.UI.Architecture
Imports SkiaSharp

Namespace Nexamas.UI.Rendering

    Friend Structure MASToastLayoutInfo
        Friend ToastId As Integer

        Friend PanelRectPx As SKRect
        Friend AccentRectPx As SKRect
        Friend TitleRectPx As SKRect
        Friend MessageRectPx As SKRect
        Friend ActionRectPx As SKRect
        Friend UndoRectPx As SKRect
        Friend CloseRectPx As SKRect
        Friend LifetimeBarRectPx As SKRect

        Friend Opacity As Single
        Friend RemainingRatio As Single
    End Structure

    ''' <summary>
    ''' Internal renderer for toast floating surfaces.
    ''' Keeps measurement, arrangement and drawing in one owned implementation so the public toast API
    ''' stays small while the visual contract remains consistent with Nexamas UI surface rendering.
    ''' </summary>
    Partial Friend NotInheritable Class MASToastRenderer
        Implements IDisposable

        Private Const LifetimeBarHorizontalInsetDip As Single = 2.0F
        Private Const LifetimeBarBottomInsetDip As Single = 7.0F
        Private Const LifetimeBarVerticalReserveDip As Single = 7.0F

        ' Toast compact glyph buttons share one geometry contract so Undo and Close never drift apart.
        ' The renderer must not compensate Undo through private padding or a smaller local button;
        ' both top-right commands are drawn through the same compact glyph-button gateway.

        Private Shared ReadOnly _toastContract As MASResolvedComponentContract =
    MASArchitectureRuntime.ResolveContractOrThrow(GetType(MASToastFloatContract))

        Private Shared ReadOnly _buttonContract As MASResolvedComponentContract =
    MASArchitectureRuntime.ResolveContractOrThrow(GetType(MASButton))

        Private ReadOnly _frameSurface As New MASSurfaceFramePainter()
        Private ReadOnly _smallButton As New GlyphButtonRenderer()
        Private ReadOnly _actionButton As New MASButtonRenderer()

        Private Shared ReadOnly _accentGradientPositions As Single() = New Single() {0.0F, 0.48F, 1.0F}
        Private Shared ReadOnly _lifetimeFillGradientPositions As Single() = New Single() {0.0F, 0.54F, 1.0F}

        Private ReadOnly _accentGradientColors As SKColor() = New SKColor(2) {SKColors.Transparent, SKColors.Transparent, SKColors.Transparent}
        Private ReadOnly _lifetimeFillGradientColors As SKColor() = New SKColor(2) {SKColors.Transparent, SKColors.Transparent, SKColors.Transparent}

        Private ReadOnly _accentClipPath As New SKPath()
        Private ReadOnly _lifetimeClipPath As New SKPath()
        Private ReadOnly _accentPaint As New SKPaint With {.IsAntialias = True, .IsDither = True, .Style = SKPaintStyle.Fill}
        Private ReadOnly _lifetimeTrackPaint As New SKPaint With {.IsAntialias = True, .IsDither = True, .Style = SKPaintStyle.Fill}
        Private ReadOnly _lifetimeTrackShinePaint As New SKPaint With {.IsAntialias = True, .IsDither = True, .Style = SKPaintStyle.Fill}
        Private ReadOnly _lifetimeFillPaint As New SKPaint With {.IsAntialias = True, .IsDither = True, .Style = SKPaintStyle.Fill}
        Private ReadOnly _lifetimeFillShinePaint As New SKPaint With {.IsAntialias = True, .IsDither = True, .Style = SKPaintStyle.Fill}
        Private ReadOnly _lifetimeCapPaint As New SKPaint With {.IsAntialias = True, .IsDither = True, .Style = SKPaintStyle.Fill}

        Private _disposed As Boolean


        Private Shared Sub DisposeOwnedSkiaResource(resource As IDisposable)
            If resource Is Nothing Then Return

            Try
                resource.Dispose()
            Catch masCaughtException As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(masCaughtException)
            End Try
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            If _disposed Then Return
            _disposed = True

            Try
                _accentPaint.Shader = Nothing
                _lifetimeFillPaint.Shader = Nothing
            Catch masCaughtException0 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(masCaughtException0)
            End Try

            DisposeOwnedSkiaResource(_accentPaint)
            DisposeOwnedSkiaResource(_lifetimeTrackPaint)
            DisposeOwnedSkiaResource(_lifetimeTrackShinePaint)
            DisposeOwnedSkiaResource(_lifetimeFillPaint)
            DisposeOwnedSkiaResource(_lifetimeFillShinePaint)
            DisposeOwnedSkiaResource(_lifetimeCapPaint)
            DisposeOwnedSkiaResource(_accentClipPath)
            DisposeOwnedSkiaResource(_lifetimeClipPath)

            Try
                _actionButton.Dispose()
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(masCaughtException1)
            End Try

            Try
                _smallButton.Dispose()
            Catch masCaughtException2 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(masCaughtException2)
            End Try

            Try
                _frameSurface.Dispose()
            Catch masCaughtException3 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(masCaughtException3)
            End Try
        End Sub

    End Class

End Namespace
