Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Values

Namespace Nexamas.UI.General

    Friend NotInheritable Class MASVisualInteractionGeometryProfiles

        Private Sub New()
        End Sub

        Friend Structure InteractionGeometryStateProfile
            Friend Shape As MASVisualInteractionOverlayShape
            Friend ExtraFillInsetUnits As Single
            Friend ExtraRingInsetUnits As Single
        End Structure

        Friend Structure InteractionGeometryProfile
            Friend Hover As InteractionGeometryStateProfile
            Friend Pressed As InteractionGeometryStateProfile
            Friend Selected As InteractionGeometryStateProfile
            Friend Focused As InteractionGeometryStateProfile
        End Structure

        Friend Shared Function Resolve(fam As CommonEnums.SurfaceFamily) As InteractionGeometryProfile
            Dim p As InteractionGeometryProfile = ResolveFamilyBaseline(fam)
            ValidateProfile(p, $"family={fam}")
            Return p
        End Function

        Friend Shared Function Resolve(kind As CommonEnums.ControlKind) As InteractionGeometryProfile
            Dim fam As CommonEnums.SurfaceFamily = CommonEnums.MapKindToFamily(kind)
            Dim p As InteractionGeometryProfile = ResolveFamilyBaseline(fam)

            Select Case kind
                Case CommonEnums.ControlKind.ListRow,
                     CommonEnums.ControlKind.TreeRow,
                     CommonEnums.ControlKind.ListViewRow,
                     CommonEnums.ControlKind.ListViewHeader

                    p = BuildListRowProfile()

                Case CommonEnums.ControlKind.ToggleSwitch,
                     CommonEnums.ControlKind.TreeView,
                     CommonEnums.ControlKind.ListView

                    p = BuildRegularClosedProfile()
            End Select

            ValidateProfile(p, $"kind={kind}")
            Return p
        End Function

        Friend Shared Function ResolveState(fam As CommonEnums.SurfaceFamily,
                                            state As MASInteractionState) As InteractionGeometryStateProfile

            Return ResolveState(Resolve(fam), state)

        End Function

        Friend Shared Function ResolveState(kind As CommonEnums.ControlKind,
                                            state As MASInteractionState) As InteractionGeometryStateProfile

            Return ResolveState(Resolve(kind), state)

        End Function

        Friend Shared Function ResolveState(profile As InteractionGeometryProfile,
                                            state As MASInteractionState) As InteractionGeometryStateProfile

            Dim normalized As MASInteractionState = MASInteractionResolver.NormalizeState(state)

            Select Case normalized

                Case MASInteractionState.Hovered
                    Return profile.Hover

                Case MASInteractionState.Pressed
                    Return profile.Pressed

                Case MASInteractionState.Selected
                    Return profile.Selected

                Case MASInteractionState.Focused
                    Return profile.Focused

                Case MASInteractionState.None,
                     MASInteractionState.Disabled

                    Return MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F)

                Case Else
                    Throw New NotSupportedException($"Unsupported interaction state: {CInt(normalized)}")

            End Select

        End Function

        Private Shared Function ResolveFamilyBaseline(fam As CommonEnums.SurfaceFamily) As InteractionGeometryProfile

            Select Case fam

                Case CommonEnums.SurfaceFamily.Row,
                     CommonEnums.SurfaceFamily.ListSurface,
                     CommonEnums.SurfaceFamily.DataGrid,
                     CommonEnums.SurfaceFamily.PropertyGrid,
                     CommonEnums.SurfaceFamily.ListBox

                    Return BuildListRowProfile()

                Case CommonEnums.SurfaceFamily.Input,
                     CommonEnums.SurfaceFamily.ComboBox,
                     CommonEnums.SurfaceFamily.ButtonMas,
                     CommonEnums.SurfaceFamily.Tile,
                     CommonEnums.SurfaceFamily.Chip,
                     CommonEnums.SurfaceFamily.TabItem,
                     CommonEnums.SurfaceFamily.CheckBox,
                     CommonEnums.SurfaceFamily.RadioButton,
                     CommonEnums.SurfaceFamily.ToggleSwitch,
                     CommonEnums.SurfaceFamily.SegmentedControl,
                     CommonEnums.SurfaceFamily.ScrollBar,
                     CommonEnums.SurfaceFamily.SelectorItem,
                     CommonEnums.SurfaceFamily.TopBar,
                     CommonEnums.SurfaceFamily.Card,
                     CommonEnums.SurfaceFamily.Media,
                     CommonEnums.SurfaceFamily.Chart,
                     CommonEnums.SurfaceFamily.Fenster,
                     CommonEnums.SurfaceFamily.DropDown,
                     CommonEnums.SurfaceFamily.DropDownMenu,
                     CommonEnums.SurfaceFamily.ContextMenu,
                     CommonEnums.SurfaceFamily.Menu,
                     CommonEnums.SurfaceFamily.GroupBox,
                     CommonEnums.SurfaceFamily.GroupBoxTitlePlate,
                     CommonEnums.SurfaceFamily.ColorPicker,
                     CommonEnums.SurfaceFamily.ColorPickerPreview,
                     CommonEnums.SurfaceFamily.ColorPickerSVBox,
                     CommonEnums.SurfaceFamily.ColorPickerHueBar,
                     CommonEnums.SurfaceFamily.ColorPickerSlot,
                     CommonEnums.SurfaceFamily.ColorPickerSwatch,
                     CommonEnums.SurfaceFamily.ColorPickerMarker,
                     CommonEnums.SurfaceFamily.TileBox,
                     CommonEnums.SurfaceFamily.Toast,
                     CommonEnums.SurfaceFamily.TabStrip,
                     CommonEnums.SurfaceFamily.PanelShell

                    Return BuildRegularClosedProfile()

                Case CommonEnums.SurfaceFamily.ButtonTal
                    Return BuildTalButtonProfile()

                Case CommonEnums.SurfaceFamily.Tooltip
                    Return BuildNoneProfile()

                Case Else
                    Throw New NotSupportedException($"No interaction geometry baseline defined for family: {fam}")

            End Select

        End Function

        Private Shared Function BuildRegularClosedProfile() As InteractionGeometryProfile
            Return New InteractionGeometryProfile With {
                .Hover = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Pressed = MakeState(MASVisualInteractionOverlayShape.Closed, 0.9F, 0.6F),
                .Selected = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Focused = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F)
            }
        End Function

        Private Shared Function BuildTalButtonProfile() As InteractionGeometryProfile
            Return New InteractionGeometryProfile With {
                .Hover = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Pressed = MakeState(MASVisualInteractionOverlayShape.Closed, 0.55F, 0.35F),
                .Selected = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Focused = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F)
            }
        End Function

        Private Shared Function BuildListRowProfile() As InteractionGeometryProfile
            Return New InteractionGeometryProfile With {
                .Hover = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Pressed = MakeState(MASVisualInteractionOverlayShape.Closed, 0.35F, 0.0F),
                .Selected = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Focused = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F)
            }
        End Function

        Private Shared Function BuildNoneProfile() As InteractionGeometryProfile
            Return New InteractionGeometryProfile With {
                .Hover = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Pressed = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Selected = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F),
                .Focused = MakeState(MASVisualInteractionOverlayShape.Closed, 0.0F, 0.0F)
            }
        End Function

        Friend Shared Function BuildClosedUniformProfile(hoverFillUnits As Single,
                                                         hoverRingUnits As Single,
                                                         pressedFillUnits As Single,
                                                         pressedRingUnits As Single,
                                                         selectedFillUnits As Single,
                                                         selectedRingUnits As Single,
                                                         focusedFillUnits As Single,
                                                         focusedRingUnits As Single) As InteractionGeometryProfile

            Dim p As New InteractionGeometryProfile With {
                .Hover = MakeState(MASVisualInteractionOverlayShape.Closed, hoverFillUnits, hoverRingUnits),
                .Pressed = MakeState(MASVisualInteractionOverlayShape.Closed, pressedFillUnits, pressedRingUnits),
                .Selected = MakeState(MASVisualInteractionOverlayShape.Closed, selectedFillUnits, selectedRingUnits),
                .Focused = MakeState(MASVisualInteractionOverlayShape.Closed, focusedFillUnits, focusedRingUnits)
            }

            ValidateProfile(p, "BuildClosedUniformProfile")
            Return p

        End Function

        Private Shared Sub ValidateProfile(profile As InteractionGeometryProfile,
                                           source As String)

            ValidateState(profile.Hover, $"{source}/Hover")
            ValidateState(profile.Pressed, $"{source}/Pressed")
            ValidateState(profile.Selected, $"{source}/Selected")
            ValidateState(profile.Focused, $"{source}/Focused")

        End Sub

        Private Shared Sub ValidateState(state As InteractionGeometryStateProfile,
                                         source As String)

            If Not [Enum].IsDefined(GetType(MASVisualInteractionOverlayShape), state.Shape) Then
                Throw New InvalidOperationException($"Invalid interaction overlay shape at {source}.")
            End If

            If Single.IsNaN(state.ExtraFillInsetUnits) OrElse
               Single.IsInfinity(state.ExtraFillInsetUnits) OrElse
               state.ExtraFillInsetUnits < 0.0F Then

                Throw New InvalidOperationException($"Invalid ExtraFillInsetUnits at {source}.")
            End If

            If Single.IsNaN(state.ExtraRingInsetUnits) OrElse
               Single.IsInfinity(state.ExtraRingInsetUnits) OrElse
               state.ExtraRingInsetUnits < 0.0F Then

                Throw New InvalidOperationException($"Invalid ExtraRingInsetUnits at {source}.")
            End If

        End Sub

        Private Shared Function MakeState(shape As MASVisualInteractionOverlayShape,
                                          extraFillInsetUnits As Single,
                                          extraRingInsetUnits As Single) As InteractionGeometryStateProfile

            Return New InteractionGeometryStateProfile With {
                .Shape = shape,
                .ExtraFillInsetUnits = SafeNonNegative(extraFillInsetUnits),
                .ExtraRingInsetUnits = SafeNonNegative(extraRingInsetUnits)
            }

        End Function

        Private Shared Function SafeNonNegative(v As Single) As Single

            If Single.IsNaN(v) OrElse Single.IsInfinity(v) OrElse v < 0.0F Then
                Throw New InvalidOperationException("Interaction geometry units must be finite and non-negative.")
            End If

            Return v

        End Function

    End Class

End Namespace