Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Controls

Namespace Nexamas.UI.Composition

    ''' <summary>
    ''' Public semantic root-screen region description.
    ''' A region describes where a control or nested layout node belongs by role, not by manual coordinates.
    ''' MASScreen consumes these descriptions and converts them into native MASLayout dock items.
    ''' </summary>
    <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
    Friend NotInheritable Class MASScreenRegion

        Friend ReadOnly Property Role As MASScreenRegionRole
        Friend ReadOnly Property Control As MASControlBase
        Friend ReadOnly Property Node As IMASLayoutNode
        Friend ReadOnly Property WidthPolicy As MASSizePolicy
        Friend ReadOnly Property HeightPolicy As MASSizePolicy
        Friend ReadOnly Property Margin As MASLayoutThickness
        Friend ReadOnly Property Key As String

        Private Sub New(role As MASScreenRegionRole,
                        control As MASControlBase,
                        node As IMASLayoutNode,
                        widthPolicy As MASSizePolicy,
                        heightPolicy As MASSizePolicy,
                        margin As MASLayoutThickness,
                        key As String)

            If control Is Nothing AndAlso node Is Nothing Then Throw New ArgumentException("A screen region must contain either a control or a layout node.")
            If control IsNot Nothing AndAlso node IsNot Nothing Then Throw New ArgumentException("A screen region cannot contain both a control and a layout node.")

            Me.Role = NormalizeRole(role)
            Me.Control = control
            Me.Node = node
            Me.WidthPolicy = widthPolicy
            Me.HeightPolicy = heightPolicy
            Me.Margin = margin
            Me.Key = If(key, String.Empty)
        End Sub

        ''' <summary>
        ''' Creates a semantic region from a MAS control. Width/height policies remain optional intent, not manual bounds.
        ''' </summary>
        Friend Shared Function FromControl(role As MASScreenRegionRole,
                                           control As MASControlBase,
                                           Optional width As MASSizePolicy = Nothing,
                                           Optional height As MASSizePolicy = Nothing,
                                           Optional margin As MASLayoutThickness = Nothing,
                                           Optional key As String = "") As MASScreenRegion

            If control Is Nothing Then Throw New ArgumentNullException(NameOf(control))
            Return New MASScreenRegion(role, control, Nothing, width, height, margin, key)
        End Function

        ''' <summary>
        ''' Creates a semantic region from a nested MAS layout node.
        ''' </summary>
        Friend Shared Function FromNode(role As MASScreenRegionRole,
                                        node As IMASLayoutNode,
                                        Optional width As MASSizePolicy = Nothing,
                                        Optional height As MASSizePolicy = Nothing,
                                        Optional margin As MASLayoutThickness = Nothing,
                                        Optional key As String = "") As MASScreenRegion

            If node Is Nothing Then Throw New ArgumentNullException(NameOf(node))
            Return New MASScreenRegion(role, Nothing, node, width, height, margin, key)
        End Function

        Friend Function ToLayoutItem() As MASLayoutItem
            Dim dock As MASLayoutDock = ResolveDock(Role)
            Dim width As MASSizePolicy = ResolveWidthPolicy(Role, WidthPolicy)
            Dim height As MASSizePolicy = ResolveHeightPolicy(Role, HeightPolicy)

            If Control IsNot Nothing Then
                Return MASComposition.DockItem(Control, dock, width, height, Margin, Key)
            End If

            Return MASComposition.DockNodeItem(Node, dock, width, height, Margin, Key)
        End Function

        Private Shared Function ResolveDock(role As MASScreenRegionRole) As MASLayoutDock
            Select Case NormalizeRole(role)
                Case MASScreenRegionRole.Header, MASScreenRegionRole.Command
                    Return MASLayoutDock.Top
                Case MASScreenRegionRole.Footer
                    Return MASLayoutDock.Bottom
                Case MASScreenRegionRole.Navigation
                    Return MASLayoutDock.Left
                Case MASScreenRegionRole.Inspector
                    Return MASLayoutDock.Right
                Case Else
                    Return MASLayoutDock.Center
            End Select
        End Function

        Private Shared Function ResolveWidthPolicy(role As MASScreenRegionRole, policy As MASSizePolicy) As MASSizePolicy
            If policy IsNot Nothing Then Return policy

            Select Case NormalizeRole(role)
                Case MASScreenRegionRole.Content
                    Return MASSizePolicy.Fill(1.0F)
                Case Else
                    Return MASSizePolicy.Auto()
            End Select
        End Function

        Private Shared Function ResolveHeightPolicy(role As MASScreenRegionRole, policy As MASSizePolicy) As MASSizePolicy
            If policy IsNot Nothing Then Return policy

            Select Case NormalizeRole(role)
                Case MASScreenRegionRole.Content
                    Return MASSizePolicy.Fill(1.0F)
                Case Else
                    Return MASSizePolicy.Auto()
            End Select
        End Function

        Private Shared Function NormalizeRole(role As MASScreenRegionRole) As MASScreenRegionRole
            If [Enum].IsDefined(GetType(MASScreenRegionRole), role) Then Return role
            Return MASScreenRegionRole.Content
        End Function

    End Class

End Namespace
