Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.General
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components


    Partial Friend NotInheritable Class SegmentedControlPainter

        Friend Sub Draw(canvas As SKCanvas,
                ctx As MASThemeContext,
                contract As MASResolvedComponentContract,
                m As SegmentedControlLayout.Metrics,
                indicatorR As SKRect,
                labels As IReadOnlyList(Of String),
                selectedIndex As Integer,
                shapeIndex As Integer,
                hoverIndex As Integer,
                dpi As Single,
                st As Style)

            If _disposed Then Return
            If canvas Is Nothing OrElse ctx Is Nothing OrElse contract Is Nothing OrElse m Is Nothing OrElse st Is Nothing Then Return

            Dim scope As MASContractRenderScope =
    MASArchitectureRuntime.CreateRenderScopeForComponent(Of SegmentedControl)(
        NameOf(SegmentedControlPainter),
        contract,
        MASRenderLayer.Surface,
        MASRenderLayer.Shadow,
        MASRenderLayer.Text,
        MASRenderLayer.Hover,
        MASRenderLayer.Pressed)

            scope.RequireAnyLayer(
    MASRenderLayer.Surface,
    MASRenderLayer.Shadow,
    MASRenderLayer.Text,
    MASRenderLayer.Hover,
    MASRenderLayer.Pressed)


            If m.PillR.IsEmpty OrElse m.Segments Is Nothing OrElse m.Segments.Length < 2 Then Return

            dpi = PixelSnap.SafeDpi(dpi)

            Dim app As IMASAppTheme = ctx.Theme
            If app Is Nothing Then Return

            Dim sw As IMASSegmentedControlTheme = MASAppThemeContracts.Families(app).SegmentedControl
            If sw Is Nothing Then Return

            Dim surfaceTheme As IMASFoundationSurfaceTheme = MASAppThemeContracts.Foundation(app).Surface
            If surfaceTheme Is Nothing Then Return

            Dim rm As MASSurfaceInteractionRing.Metrics = MASSurfaceInteractionRing.GetMetrics(dpi)

            Dim pillR As SKRect = MASSurfaceInteractionRing.SnapBaseRect(m.PillR, rm)
            If pillR.Width <= 1.0F OrElse pillR.Height <= 1.0F Then Return

            Dim radBase As Single =
   MASRadiusResolver.ResolveSurfacePx(
    contract:=contract,
    rPx:=pillR,
    dpi:=dpi)

            radBase = PixelSnap.SafeRadius(radBase)

            _shadow.DrawLayeredShadow(
    canvas:=canvas,
    r:=pillR,
    contract:=contract,
    dpi:=dpi,
    surfaceTheme:=surfaceTheme
)
            Dim pillSpec As MASVisualPrimitivesPainter.ChipBaseSpec =
                BuildSegmentedControlPillSpec(sw)

            Dim pillFx As MASVisualPrimitivesPainter.ChipFxSpec =
                BuildSegmentedControlPillFxSpec(sw.Track)

            _p.DrawChipBaseNoShadow(canvas, ctx, pillR, radBase, dpi, pillSpec)
            _p.DrawChipFxSSOT(canvas, pillR, radBase, dpi, pillSpec, pillFx)

            DrawSegmentedControlPillRim(
                canvas:=canvas,
                pillR:=pillR,
                radBase:=radBase,
                dpi:=dpi,
                hairW:=m.HairW,
                sw:=sw
            )

            MASVisualPrimitivesPainter.WithClipRoundRect(
                canvas:=canvas,
                r:=pillR,
                radiusPx:=radBase,
                drawAction:=Sub()

                                If selectedIndex >= 0 AndAlso selectedIndex < m.Segments.Length Then
                                    Dim indBase As SKRect = MASSurfaceInteractionRing.SnapBaseRect(indicatorR, rm)

                                    If indBase.Width > 1.0F AndAlso indBase.Height > 1.0F Then
                                        Dim segmentShapeIndex As Integer =
                                            Math.Max(0, Math.Min(shapeIndex, m.Segments.Length - 1))

                                        Dim indVisual As SKRect =
                                            BuildIndicatorVisualRect(
                                                r:=indBase,
                                                segmentIndex:=segmentShapeIndex,
                                                segmentCount:=m.Segments.Length,
                                                dpi:=dpi,
                                                hairW:=m.HairW,
                                                rm:=rm
                                            )

                                        If indVisual.Width > 1.0F AndAlso indVisual.Height > 1.0F Then
                                            Dim indicatorRadius As Single =
                                              MASRadiusResolver.ResolveSurfacePx(
                                                contract:=contract,
                                                rPx:=indVisual,
                                                dpi:=dpi)
                                            indicatorRadius = PixelSnap.SafeRadius(indicatorRadius)

                                            Dim indicatorFx As MASVisualPrimitivesPainter.ChipFxSpec =
                                                BuildSegmentedControlIndicatorFxSpec(app)

                                            DrawIndicatorMaterialPerCorner(
                                                canvas:=canvas,
                                                r:=indVisual,
                                                dpi:=dpi,
                                                radiusPx:=indicatorRadius,
                                                segmentIndex:=segmentShapeIndex,
                                                segmentCount:=m.Segments.Length,
                                                fillTop:=sw.Indicator.FillTop,
                                                fillBottom:=sw.Indicator.FillBottom,
                                                fxSpec:=indicatorFx,
                                                hairW:=m.HairW,
                                                app:=app
                                            )

                                            _shadow.DrawInnerHalo(
                                            canvas:=canvas,
                                            r:=indVisual,
                                            contract:=contract,
                                            dpi:=dpi,
                                            surfaceTheme:=surfaceTheme,
                                            alpha:=20,
                                            sigmaDip:=2.0F,
                                            strokeDip:=0.86F,
                                            insetDip:=0.8F
)
                                            Dim selSpec As MASVisualInteractionOverlaySpec =
                                            MASInteractionResolver.Build(
                                                contract:=contract,
                                                state:=MASInteractionState.Selected,
                                                theme:=app)
                                            If selSpec.FillEnabled OrElse selSpec.RingEnabled Then
                                                MASSurfaceInteractionRing.DrawSegmentOverlay(
                                                    canvas:=canvas,
                                                    baseRectPx:=indVisual,
                                                    baseRadiusPx:=indicatorRadius,
                                                    m:=rm,
                                                    spec:=selSpec,
                                                    segmentIndex:=segmentShapeIndex,
                                                    segmentCount:=m.Segments.Length
                                                )
                                            End If
                                        End If
                                    End If
                                End If

                                If hoverIndex >= 0 AndAlso hoverIndex < m.Segments.Length AndAlso hoverIndex <> selectedIndex Then
                                    Dim hovBase As SKRect = MASSurfaceInteractionRing.SnapBaseRect(m.Segments(hoverIndex), rm)

                                    Dim hovSpec As MASVisualInteractionOverlaySpec =
                                    MASInteractionResolver.Build(
                                        contract:=contract,
                                        state:=MASInteractionState.Hovered,
                                        theme:=app)
                                    If hovSpec.FillEnabled OrElse hovSpec.RingEnabled Then
                                        MASSurfaceInteractionRing.DrawSegmentOverlay(
                                            canvas:=canvas,
                                            baseRectPx:=hovBase,
                                            baseRadiusPx:=radBase,
                                            m:=rm,
                                            spec:=hovSpec,
                                            segmentIndex:=hoverIndex,
                                            segmentCount:=m.Segments.Length
                                        )
                                    End If
                                End If

                                Dim nudgeY As Single = st.LabelBaselineNudgeDip * dpi

                                For i As Integer = 0 To m.Segments.Length - 1
                                    Dim label As String =
                                        If(labels IsNot Nothing AndAlso i < labels.Count, labels(i), String.Empty)

                                    If String.IsNullOrEmpty(label) Then Continue For

                                    Dim seg As SKRect = m.Segments(i)
                                    seg = MASSurfaceInteractionRing.SnapBaseRect(seg, rm)

                                    Dim isSel As Boolean = (i = selectedIndex)
                                    Dim isHot As Boolean = (i = hoverIndex AndAlso i <> selectedIndex)

                                    Dim col As SKColor = ResolveLabelColor(
                                        isSelected:=isSel,
                                        isHover:=isHot,
                                        sw:=sw,
                                        app:=app
                                    )

                                    Dim styleKind As MASTypography.MASTextStyle =
                                        If(isSel, st.TextStyleSelected, st.TextStyleIdle)

                                    Dim bounds As SKRect = seg
                                    bounds.Offset(0.0F, nudgeY)

                                    TypographyTextPrimitives.DrawSingleLineText(
                                        canvas:=canvas,
                                        ctx:=ctx,
                                        text:=label,
                                        bounds:=bounds,
                                        dpi:=dpi,
                                        style:=styleKind,
                                        color:=col,
                                        align:=TypographyTextPrimitives.TextAlign.Center,
                                        drawShadow:=False
                                    )
                                Next

                            End Sub)
        End Sub

    End Class

End Namespace
