Option Strict On
Option Explicit On

Imports System
Imports System.Globalization
Imports System.Windows.Forms
Imports Nexamas.UI.Controls
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Friend Enum MASSplitButtonSegment
        None = 0
        Main = 1
        Menu = 2
    End Enum

    Friend Structure MASSplitButtonSegmentRects
        Friend Main As SKRect
        Friend Menu As SKRect
    End Structure

    ''' <summary>
    ''' Friend-owned segmentation policy for MASSplitButton. It centralizes RTL
    ''' segment geometry, keyboard segment movement, normalized values, and activation
    ''' rules while preserving the single DropDownMenu/FloatRuntime route.
    ''' </summary>
    Friend NotInheritable Class MASSplitButtonSegmentPolicy
        Private Sub New()
        End Sub

        Friend Shared Function NormalizeText(value As String) As String
            Return If(value, String.Empty)
        End Function

        Friend Shared Function NormalizeTooltip(value As String) As String
            Return If(value, String.Empty)
        End Function

        Friend Shared Function NormalizeIntent(value As MASButtonIntent) As MASButtonIntent
            If [Enum].IsDefined(GetType(MASButtonIntent), value) Then Return value
            Return MASButtonIntent.Default
        End Function

        Friend Shared Function NormalizeIconPlacement(value As MASButtonIconPlacement) As MASButtonIconPlacement
            If [Enum].IsDefined(GetType(MASButtonIconPlacement), value) Then Return value
            Return MASButtonIconPlacement.Left
        End Function

        Friend Shared Function CanActivate(isEnabled As Boolean, isVisible As Boolean) As Boolean
            Return isEnabled AndAlso isVisible
        End Function

        Friend Shared Function ResolveSegmentRects(boundsPx As SKRect,
                                                   dpi As Single,
                                                   isRightToLeft As Boolean) As MASSplitButtonSegmentRects
            dpi = SafeDpi(dpi)
            If boundsPx.Width <= 1.0F OrElse boundsPx.Height <= 1.0F Then Return New MASSplitButtonSegmentRects()

            Dim menuWidth As Single = Math.Min(Math.Max(ButtonTokens.SplitButtonMenuWidth * dpi, 28.0F * dpi), Math.Max(1.0F, boundsPx.Width * 0.42F))
            Dim menu As SKRect
            Dim main As SKRect

            If isRightToLeft Then
                menu = New SKRect(boundsPx.Left, boundsPx.Top, boundsPx.Left + menuWidth, boundsPx.Bottom)
                main = New SKRect(menu.Right, boundsPx.Top, boundsPx.Right, boundsPx.Bottom)
            Else
                menu = New SKRect(boundsPx.Right - menuWidth, boundsPx.Top, boundsPx.Right, boundsPx.Bottom)
                main = New SKRect(boundsPx.Left, boundsPx.Top, menu.Left, boundsPx.Bottom)
            End If

            Return New MASSplitButtonSegmentRects With {
                .Main = SnapRectHalf(main),
                .Menu = SnapRectHalf(menu)
            }
        End Function

        Friend Shared Function HitTest(boundsPx As SKRect,
                                       ptPx As SKPoint,
                                       dpi As Single,
                                       isRightToLeft As Boolean) As MASSplitButtonSegment
            If boundsPx.Width <= 1.0F OrElse boundsPx.Height <= 1.0F Then Return MASSplitButtonSegment.None
            If Not boundsPx.Contains(ptPx.X, ptPx.Y) Then Return MASSplitButtonSegment.None

            Dim rects As MASSplitButtonSegmentRects = ResolveSegmentRects(boundsPx, dpi, isRightToLeft)
            If rects.Menu.Contains(ptPx.X, ptPx.Y) Then Return MASSplitButtonSegment.Menu
            If rects.Main.Contains(ptPx.X, ptPx.Y) Then Return MASSplitButtonSegment.Main
            Return MASSplitButtonSegment.None
        End Function

        Friend Shared Function ResolveKeyboardSegment(current As MASSplitButtonSegment,
                                                      keyCode As Keys,
                                                      isRightToLeft As Boolean) As MASSplitButtonSegment
            If current = MASSplitButtonSegment.None Then current = MASSplitButtonSegment.Main

            Select Case keyCode
                Case Keys.Left
                    If isRightToLeft Then
                        Return If(current = MASSplitButtonSegment.Menu, MASSplitButtonSegment.Main, MASSplitButtonSegment.Menu)
                    End If
                    Return If(current = MASSplitButtonSegment.Main, MASSplitButtonSegment.Menu, MASSplitButtonSegment.Main)

                Case Keys.Right
                    If isRightToLeft Then
                        Return If(current = MASSplitButtonSegment.Main, MASSplitButtonSegment.Menu, MASSplitButtonSegment.Main)
                    End If
                    Return If(current = MASSplitButtonSegment.Menu, MASSplitButtonSegment.Main, MASSplitButtonSegment.Menu)
            End Select

            Return current
        End Function

        Friend Shared Function IsPrimaryActivationKey(keyCode As Keys) As Boolean
            Return keyCode = Keys.Enter OrElse keyCode = Keys.Space
        End Function

        Friend Shared Function IsMenuActivationKey(keyCode As Keys) As Boolean
            Return keyCode = Keys.Down OrElse keyCode = Keys.Apps OrElse keyCode = Keys.F4
        End Function

        Friend Shared Function IsRightToLeftCulture() As Boolean
            Return Nexamas.UI.Localization.MASLocalization.IsCurrentRightToLeft()
        End Function

        Private Shared Function SafeDpi(dpi As Single) As Single
            If Single.IsNaN(dpi) OrElse Single.IsInfinity(dpi) OrElse dpi <= 0.0F Then Return 1.0F
            If dpi < 1.0F Then Return 1.0F
            Return dpi
        End Function

        Private Shared Function SnapHalf(value As Single) As Single
            Return CSng(Math.Round(value / 0.5F) * 0.5F)
        End Function

        Private Shared Function SnapRectHalf(rect As SKRect) As SKRect
            Return New SKRect(
                SnapHalf(rect.Left),
                SnapHalf(rect.Top),
                SnapHalf(rect.Right),
                SnapHalf(rect.Bottom)
            )
        End Function

    End Class

End Namespace
