Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Controls
Imports Nexamas.UI.Layout

Namespace Nexamas.UI.Application

    ''' <summary>
    ''' Public semantic alignment vocabulary for action groups. Consumers choose where the group lives
    ''' inside its available layout slot; MASLayout resolves the final logical bounds.
    ''' </summary>
    Public Enum MASApplicationActionGroupAlignment
        Start = 0
        Center = 1
        [End] = 2
    End Enum

    ''' <summary>
    ''' Public action-group layout builder used through MASApplicationLayoutPageBuilder.ActionGroup(...).
    ''' It gives application screens an official way to declare button/action rows with equal item sizing,
    ''' semantic spacing, and start/center/end placement without hard-coded widths or x coordinates.
    ''' </summary>
    Public NotInheritable Class MASApplicationActionGroupLayoutBuilder
        Private ReadOnly _children As New List(Of MASApplicationLayoutControlEntry)()
        Private _spacing As Single = MASLayoutSpacingResolver.ResolveBase(MASLayoutSpacing.Small)
        Private _padding As MASLayoutInset = MASLayoutInset.Empty
        Private _groupSizingMode As MASLayoutGroupSizingMode = MASLayoutGroupSizingMode.EqualWidth
        Private _alignment As MASApplicationActionGroupAlignment = MASApplicationActionGroupAlignment.[End]
        Private _crossAlignment As MASLayoutCrossAlignment = MASLayoutCrossAlignment.Center

        Friend Sub New()
        End Sub

        ''' <summary>
        ''' Uses the official MASLayout semantic spacing vocabulary between actions.
        ''' </summary>
        Public Function Spacing(value As MASLayoutSpacing) As MASApplicationActionGroupLayoutBuilder
            _spacing = MASLayoutSpacingResolver.ResolveBase(value)
            Return Me
        End Function

        ''' <summary>
        ''' Alias for Spacing(...), useful when the action group is read as a row of buttons.
        ''' </summary>
        Public Function Gap(value As MASLayoutSpacing) As MASApplicationActionGroupLayoutBuilder
            Return Spacing(value)
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function Spacing(value As Single) As MASApplicationActionGroupLayoutBuilder
            _spacing = MASApplicationLayoutPageBuilder.SafeNonNegative(value)
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function Gap(value As Single) As MASApplicationActionGroupLayoutBuilder
            Return Spacing(value)
        End Function

        ''' <summary>
        ''' Uses semantic padding around the action group instead of raw logical numbers.
        ''' </summary>
        Public Function Padding(value As MASLayoutSpacing) As MASApplicationActionGroupLayoutBuilder
            _padding = MASLayoutSpacingResolver.ResolveInsetBase(value)
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function Padding(all As Single) As MASApplicationActionGroupLayoutBuilder
            _padding = New MASLayoutInset(all)
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function Padding(left As Single,
                                top As Single,
                                right As Single,
                                bottom As Single) As MASApplicationActionGroupLayoutBuilder
            _padding = New MASLayoutInset(left, top, right, bottom)
            Return Me
        End Function

        ''' <summary>
        ''' Makes all actions use the largest measured item width. This is the default for ActionGroup.
        ''' </summary>
        Public Function EqualItemWidth() As MASApplicationActionGroupLayoutBuilder
            _groupSizingMode = MASLayoutGroupSizingMode.EqualWidth
            Return Me
        End Function

        ''' <summary>
        ''' Makes all actions use the largest measured width and height in the group.
        ''' </summary>
        Public Function EqualItemSize() As MASApplicationActionGroupLayoutBuilder
            _groupSizingMode = MASLayoutGroupSizingMode.EqualSize
            Return Me
        End Function

        ''' <summary>
        ''' Restores per-action intrinsic sizing for cases where equal action buttons are not desired.
        ''' </summary>
        Public Function IntrinsicItemSize() As MASApplicationActionGroupLayoutBuilder
            _groupSizingMode = MASLayoutGroupSizingMode.Intrinsic
            Return Me
        End Function

        Public Function AlignStart() As MASApplicationActionGroupLayoutBuilder
            _alignment = MASApplicationActionGroupAlignment.Start
            Return Me
        End Function

        Public Function AlignCenter() As MASApplicationActionGroupLayoutBuilder
            _alignment = MASApplicationActionGroupAlignment.Center
            Return Me
        End Function

        Public Function AlignEnd() As MASApplicationActionGroupLayoutBuilder
            _alignment = MASApplicationActionGroupAlignment.[End]
            Return Me
        End Function

        Public Function Align(alignment As MASApplicationActionGroupAlignment) As MASApplicationActionGroupLayoutBuilder
            _alignment = NormalizeAlignment(alignment)
            Return Me
        End Function

        ''' <summary>
        ''' Adds an action control. The default intent keeps the action intrinsic while the group may equalize
        ''' item width through MASLayout, not through control.Width assignments.
        ''' </summary>
        Public Function Add(control As MASControlBase,
                            Optional sizeIntent As MASSize = Nothing) As MASApplicationActionGroupLayoutBuilder
            If control IsNot Nothing Then
                _children.Add(New MASApplicationLayoutControlEntry(control, sizeIntent, MASLayoutCrossAlignment.Stretch))
            End If

            Return Me
        End Function

        Friend Function BuildNode(Optional sizeProfile As MASSizeProfile = Nothing) As MASLayoutNode
            Dim profile As MASSizeProfile = MASSizeProfile.Normalize(sizeProfile)
            Dim nodes As New List(Of MASLayoutNode)()

            For Each child As MASApplicationLayoutControlEntry In _children
                nodes.Add(child.BuildNode())
            Next

            Return MASLayoutBuilder.StackHorizontal(nodes,
                                                    MASLayoutSpacingResolver.ScaleLength(_spacing, profile),
                                                    MASLayoutSpacingResolver.ScaleInset(_padding, profile),
                                                    _crossAlignment,
                                                    _groupSizingMode,
                                                    ResolveMainAlignment(_alignment))
        End Function

        Friend Sub CollectControls(target As IList(Of MASControlBase))
            If target Is Nothing Then Return
            For Each child As MASApplicationLayoutControlEntry In _children
                child.CollectControls(target)
            Next
        End Sub

        Private Shared Function NormalizeAlignment(value As MASApplicationActionGroupAlignment) As MASApplicationActionGroupAlignment
            If [Enum].IsDefined(GetType(MASApplicationActionGroupAlignment), value) Then Return value
            Return MASApplicationActionGroupAlignment.[End]
        End Function

        Private Shared Function ResolveMainAlignment(value As MASApplicationActionGroupAlignment) As MASLayoutMainAlignment
            Select Case NormalizeAlignment(value)
                Case MASApplicationActionGroupAlignment.Center
                    Return MASLayoutMainAlignment.Center
                Case MASApplicationActionGroupAlignment.[End]
                    Return MASLayoutMainAlignment.[End]
                Case Else
                    Return MASLayoutMainAlignment.Start
            End Select
        End Function
    End Class

End Namespace
