Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Composition

    ''' <summary>
    ''' Public Phase 1 screen facade.
    ''' A Screen describes a root composition and does not replace MASSkiaRootHost, ControlsLayer, ThemeHost,
    ''' rendering, input routing, overlay, scroll runtime, or the host lifecycle.
    ''' </summary>
    <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
    Friend NotInheritable Class MASScreen

        Private Sub New()
        End Sub

        ''' <summary>
        ''' Advanced/precise dock screen entry point when each region already has a MASLayoutItem.
        ''' </summary>
        Friend Shared Function Dock(children As IEnumerable(Of MASLayoutItem),
                                    Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Return MASComposition.Dock(children, padding)
        End Function


        ''' <summary>
        ''' Creates a root screen layout from semantic regions. Consumers describe roles such as Header,
        ''' Navigation, Content, Inspector, and Footer; MASLayout owns the final slots and sizes.
        ''' Region defaults are Auto except Content, which fills the remaining center area.
        ''' </summary>
        Friend Shared Function Regions(aregions As IEnumerable(Of MASScreenRegion),
                                       Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim items As New List(Of MASLayoutItem)()

            If aregions IsNot Nothing Then
                For Each region As MASScreenRegion In aregions
                    If region IsNot Nothing Then items.Add(region.ToLayoutItem())
                Next
            End If

            Return MASComposition.Dock(items.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Creates a smart semantic screen-region layout node. Unlike raw Dock(...), this node owns
        ''' the root screen policy inside Nexamas UI: edge regions are content-sized, Content remains
        ''' protected, and consuming projects do not provide manual coordinates.
        ''' </summary>
        Friend Shared Function RegionLayout(aregions As IEnumerable(Of MASScreenRegion),
                                            Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Return New MASScreenRegionLayoutNode(aregions, padding)
        End Function

        ''' <summary>
        ''' Creates the official command-action row used by application Command regions.
        ''' Nexamas UI owns action preferred width, minimum width, height, spacing,
        ''' background padding, proportional shrink, and overflow into More when the row
        ''' can no longer fit safely inside its semantic Command slot.
        ''' </summary>
        Friend Shared Function CommandActions(actions As IEnumerable(Of MASControlBase)) As IMASLayoutNode
            Dim profile As MASSizeProfile = MASRuntimeSizeProfileService.Current

            Return New MASCommandActionsLayoutNode(
                actions:=actions,
                spacing:=MASScreenRegionLayoutTokens.ResolveCommandActionSpacing(profile),
                padding:=CommandBackgroundPadding())
        End Function

        ''' <summary>
        ''' Returns the official command-background padding used by CommandActions(...).
        ''' Renderers that draw a command background should consume this gateway so visual
        ''' background bounds and reserved layout padding stay identical.
        ''' </summary>
        Friend Shared Function CommandBackgroundPadding() As MASLayoutThickness
            Return MASScreenRegionLayoutTokens.ResolveCommandBackgroundPadding(MASRuntimeSizeProfileService.Current)
        End Function

        ''' <summary>
        ''' Resolves the official visual card bounds for an application Command row. The
        ''' command actions remain centered inside the visual card and the trailing edge can
        ''' align with the following workspace row, allowing app shells to draw the card from
        ''' semantic layout facts instead of expanding a button union with local numbers.
        ''' </summary>
        Friend Shared Function CommandBackgroundBounds(commandActionBounds As SKRect,
                                                       followingWorkspaceBounds As SKRect,
                                                       Optional followingApplicationSurfaceGap As Single = 0.0F) As SKRect
            If commandActionBounds.IsEmpty Then Return SKRect.Empty

            Dim padding As MASLayoutThickness = CommandBackgroundPadding()
            Dim hasFollowing As Boolean = Not followingWorkspaceBounds.IsEmpty

            Dim left As Single = commandActionBounds.Left - padding.Left
            Dim right As Single = commandActionBounds.Right + padding.Right

            If hasFollowing Then
                left = Math.Min(left, followingWorkspaceBounds.Left)
                right = Math.Max(right, followingWorkspaceBounds.Right)
            End If

            Dim bottom As Single = commandActionBounds.Bottom + padding.Bottom
            If hasFollowing Then
                Dim candidateBottom As Single = followingWorkspaceBounds.Top - Math.Max(0.0F, followingApplicationSurfaceGap)
                If candidateBottom > commandActionBounds.Bottom Then bottom = candidateBottom
            End If

            Dim minimumTop As Single = commandActionBounds.Top - padding.Top
            Dim top As Single = minimumTop

            If bottom > commandActionBounds.Bottom Then
                Dim actionCenterY As Single = (commandActionBounds.Top + commandActionBounds.Bottom) / 2.0F
                Dim centeredTop As Single = (2.0F * actionCenterY) - bottom
                top = Math.Min(minimumTop, centeredTop)
            End If

            If right <= left OrElse bottom <= top Then Return SKRect.Empty
            Return New SKRect(left, top, right, bottom)
        End Function

        ''' <summary>
        ''' Creates a common application screen using semantic region roles instead of manual coordinates.
        ''' This recipe is intentionally generic: it does not know about any consuming product or feature name.
        ''' </summary>
        Friend Shared Function Application(Optional header As MASControlBase = Nothing,
                                           Optional command As MASControlBase = Nothing,
                                           Optional navigation As MASControlBase = Nothing,
                                           Optional content As MASControlBase = Nothing,
                                           Optional inspector As MASControlBase = Nothing,
                                           Optional footer As MASControlBase = Nothing,
                                           Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim regionsList As New List(Of MASScreenRegion)()
            AddRegionControl(regionsList, MASScreenRegionRole.Header, header)
            AddRegionControl(regionsList, MASScreenRegionRole.Command, command)
            AddRegionControl(regionsList, MASScreenRegionRole.Navigation, navigation)
            AddRegionControl(regionsList, MASScreenRegionRole.Content, content)
            AddRegionControl(regionsList, MASScreenRegionRole.Inspector, inspector)
            AddRegionControl(regionsList, MASScreenRegionRole.Footer, footer)

            Return Regions(regionsList.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Creates a smart common application screen using semantic roles instead of manual
        ''' coordinates. This is the preferred route for product windows that want Nexamas UI
        ''' to own root-region sizing and content protection.
        ''' </summary>
        Friend Shared Function ApplicationRegionLayout(Optional header As MASControlBase = Nothing,
                                                       Optional command As MASControlBase = Nothing,
                                                       Optional navigation As MASControlBase = Nothing,
                                                       Optional content As MASControlBase = Nothing,
                                                       Optional inspector As MASControlBase = Nothing,
                                                       Optional footer As MASControlBase = Nothing,
                                                       Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim regionsList As New List(Of MASScreenRegion)()
            AddRegionControl(regionsList, MASScreenRegionRole.Header, header)
            AddRegionControl(regionsList, MASScreenRegionRole.Command, command)
            AddRegionControl(regionsList, MASScreenRegionRole.Navigation, navigation)
            AddRegionControl(regionsList, MASScreenRegionRole.Content, content)
            AddRegionControl(regionsList, MASScreenRegionRole.Inspector, inspector)
            AddRegionControl(regionsList, MASScreenRegionRole.Footer, footer)

            Return RegionLayout(regionsList.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Creates a common application screen using nested MAS layout nodes as regions.
        ''' </summary>
        Friend Shared Function ApplicationNodes(Optional header As IMASLayoutNode = Nothing,
                                                Optional command As IMASLayoutNode = Nothing,
                                                Optional navigation As IMASLayoutNode = Nothing,
                                                Optional content As IMASLayoutNode = Nothing,
                                                Optional inspector As IMASLayoutNode = Nothing,
                                                Optional footer As IMASLayoutNode = Nothing,
                                                Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim regionsList As New List(Of MASScreenRegion)()
            AddRegionNode(regionsList, MASScreenRegionRole.Header, header)
            AddRegionNode(regionsList, MASScreenRegionRole.Command, command)
            AddRegionNode(regionsList, MASScreenRegionRole.Navigation, navigation)
            AddRegionNode(regionsList, MASScreenRegionRole.Content, content)
            AddRegionNode(regionsList, MASScreenRegionRole.Inspector, inspector)
            AddRegionNode(regionsList, MASScreenRegionRole.Footer, footer)

            Return Regions(regionsList.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Creates a smart common application screen from nested MAS layout nodes.
        ''' </summary>
        Friend Shared Function ApplicationNodeRegionLayout(Optional header As IMASLayoutNode = Nothing,
                                                           Optional command As IMASLayoutNode = Nothing,
                                                           Optional navigation As IMASLayoutNode = Nothing,
                                                           Optional content As IMASLayoutNode = Nothing,
                                                           Optional inspector As IMASLayoutNode = Nothing,
                                                           Optional footer As IMASLayoutNode = Nothing,
                                                           Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim regionsList As New List(Of MASScreenRegion)()
            AddRegionNode(regionsList, MASScreenRegionRole.Header, header)
            AddRegionNode(regionsList, MASScreenRegionRole.Command, command)
            AddRegionNode(regionsList, MASScreenRegionRole.Navigation, navigation)
            AddRegionNode(regionsList, MASScreenRegionRole.Content, content)
            AddRegionNode(regionsList, MASScreenRegionRole.Inspector, inspector)
            AddRegionNode(regionsList, MASScreenRegionRole.Footer, footer)

            Return RegionLayout(regionsList.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Creates a dock screen from common MASControlBase root regions.
        ''' Edge regions default to intrinsic Auto size and Content fills the center.
        ''' Consumers pass Fixed/Range/Fill policies only when they intentionally want that behavior.
        ''' </summary>
        Friend Shared Function Dock(Optional top As MASControlBase = Nothing,
                                    Optional bottom As MASControlBase = Nothing,
                                    Optional left As MASControlBase = Nothing,
                                    Optional right As MASControlBase = Nothing,
                                    Optional content As MASControlBase = Nothing,
                                    Optional topHeight As MASSizePolicy = Nothing,
                                    Optional bottomHeight As MASSizePolicy = Nothing,
                                    Optional leftWidth As MASSizePolicy = Nothing,
                                    Optional rightWidth As MASSizePolicy = Nothing,
                                    Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim items As New List(Of MASLayoutItem)()

            AddDockControl(items, top, MASLayoutDock.Top, Nothing, If(topHeight, MASSizePolicy.Auto()))
            AddDockControl(items, bottom, MASLayoutDock.Bottom, Nothing, If(bottomHeight, MASSizePolicy.Auto()))
            AddDockControl(items, left, MASLayoutDock.Left, If(leftWidth, MASSizePolicy.Auto()), Nothing)
            AddDockControl(items, right, MASLayoutDock.Right, If(rightWidth, MASSizePolicy.Auto()), Nothing)
            AddDockControl(items, content, MASLayoutDock.Center, MASSizePolicy.Fill(1.0F), MASSizePolicy.Fill(1.0F))

            Return MASComposition.Dock(items.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Creates a dock screen from nested layout nodes.
        ''' Use this for screens whose top bar, sidebar, or content are themselves composed layouts.
        ''' </summary>
        Friend Shared Function DockNodes(Optional top As IMASLayoutNode = Nothing,
                                         Optional bottom As IMASLayoutNode = Nothing,
                                         Optional left As IMASLayoutNode = Nothing,
                                         Optional right As IMASLayoutNode = Nothing,
                                         Optional content As IMASLayoutNode = Nothing,
                                         Optional topHeight As MASSizePolicy = Nothing,
                                         Optional bottomHeight As MASSizePolicy = Nothing,
                                         Optional leftWidth As MASSizePolicy = Nothing,
                                         Optional rightWidth As MASSizePolicy = Nothing,
                                         Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Dim items As New List(Of MASLayoutItem)()

            AddDockNode(items, top, MASLayoutDock.Top, Nothing, If(topHeight, MASSizePolicy.Auto()))
            AddDockNode(items, bottom, MASLayoutDock.Bottom, Nothing, If(bottomHeight, MASSizePolicy.Auto()))
            AddDockNode(items, left, MASLayoutDock.Left, If(leftWidth, MASSizePolicy.Auto()), Nothing)
            AddDockNode(items, right, MASLayoutDock.Right, If(rightWidth, MASSizePolicy.Auto()), Nothing)
            AddDockNode(items, content, MASLayoutDock.Center, MASSizePolicy.Fill(1.0F), MASSizePolicy.Fill(1.0F))

            Return MASComposition.Dock(items.ToArray(), padding)
        End Function

        ''' <summary>
        ''' Common app shell: optional top bar, optional left sidebar, and required/optional content region.
        ''' It is only a dock recipe and does not create a navigation system.
        ''' </summary>
        Friend Shared Function AppShell(Optional topBar As MASControlBase = Nothing,
                                        Optional sidebar As MASControlBase = Nothing,
                                        Optional content As MASControlBase = Nothing,
                                        Optional topBarHeight As MASSizePolicy = Nothing,
                                        Optional sidebarWidth As MASSizePolicy = Nothing,
                                        Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Return Dock(
                top:=topBar,
                left:=sidebar,
                content:=content,
                topHeight:=If(topBarHeight, MASSizePolicy.Auto()),
                leftWidth:=If(sidebarWidth, MASSizePolicy.Auto()),
                padding:=padding
            )
        End Function

        ''' <summary>
        ''' Common content shell with optional top and bottom bars around a center content region.
        ''' </summary>
        Friend Shared Function ContentShell(Optional top As MASControlBase = Nothing,
                                            Optional content As MASControlBase = Nothing,
                                            Optional bottom As MASControlBase = Nothing,
                                            Optional topHeight As MASSizePolicy = Nothing,
                                            Optional bottomHeight As MASSizePolicy = Nothing,
                                            Optional padding As MASLayoutThickness = Nothing) As IMASLayoutNode

            Return Dock(
                top:=top,
                bottom:=bottom,
                content:=content,
                topHeight:=If(topHeight, MASSizePolicy.Auto()),
                bottomHeight:=If(bottomHeight, MASSizePolicy.Auto()),
                padding:=padding
            )
        End Function

        Private Shared Sub AddDockControl(items As List(Of MASLayoutItem),
                                          control As MASControlBase,
                                          dock As MASLayoutDock,
                                          width As MASSizePolicy,
                                          height As MASSizePolicy)
            If items Is Nothing OrElse control Is Nothing Then Return

            items.Add(
                MASComposition.DockItem(
                    control:=control,
                    dock:=dock,
                    width:=width,
                    height:=height
                )
            )
        End Sub

        Private Shared Sub AddDockNode(items As List(Of MASLayoutItem),
                                       node As IMASLayoutNode,
                                       dock As MASLayoutDock,
                                       width As MASSizePolicy,
                                       height As MASSizePolicy)
            If items Is Nothing OrElse node Is Nothing Then Return

            items.Add(
                MASComposition.DockNodeItem(
                    node:=node,
                    dock:=dock,
                    width:=width,
                    height:=height
                )
            )
        End Sub


        Private Shared Sub AddRegionControl(items As List(Of MASScreenRegion),
                                            role As MASScreenRegionRole,
                                            control As MASControlBase)
            If items Is Nothing OrElse control Is Nothing Then Return
            items.Add(MASScreenRegion.FromControl(role, control))
        End Sub

        Private Shared Sub AddRegionNode(items As List(Of MASScreenRegion),
                                         role As MASScreenRegionRole,
                                         node As IMASLayoutNode)
            If items Is Nothing OrElse node Is Nothing Then Return
            items.Add(MASScreenRegion.FromNode(role, node))
        End Sub

    End Class

End Namespace
