Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASDashboardGrid

#Region "Friend hosted widget content contract"

        Private ReadOnly _hostedWidgetContent As New Dictionary(Of String, MASControlBase)(StringComparer.Ordinal)
        Private _hostedWidgetLifecycleGeneration As Integer

        Friend Function HostWidgetContent(widgetKey As String,
                                          child As MASControlBase) As Boolean
            If child Is Nothing Then Return False
            Dim key As String = MASDashboardGridPolicy.NormalizeKey(widgetKey, "widget", 1)
            If FindWidgetIndex(key) < 0 Then Return False

            Dim existing As MASControlBase = Nothing
            If _hostedWidgetContent.TryGetValue(key, existing) Then
                If Object.ReferenceEquals(existing, child) Then Return True
                If existing IsNot Nothing Then UnregisterChild(existing)
                _hostedWidgetContent.Remove(key)
            End If

            RegisterChild(child)
            If String.IsNullOrWhiteSpace(child.Name) Then child.Name = "DashboardWidgetHost_" & key
            _hostedWidgetContent.Add(key, child)
            _hostedWidgetLifecycleGeneration += 1
            InvalidateVisual()
            Return True
        End Function

        Friend Function UnhostWidgetContent(widgetKey As String,
                                            Optional disposeChild As Boolean = False) As Boolean
            Dim key As String = MASDashboardGridPolicy.NormalizeKey(widgetKey, "widget", 1)
            Dim child As MASControlBase = Nothing
            If Not _hostedWidgetContent.TryGetValue(key, child) Then Return False
            _hostedWidgetContent.Remove(key)
            If child IsNot Nothing Then
                UnregisterChild(child)
                If disposeChild Then child.Dispose()
            End If
            _hostedWidgetLifecycleGeneration += 1
            InvalidateVisual()
            Return True
        End Function

        Friend Function ClearHostedWidgetContent(Optional disposeChildren As Boolean = False) As Boolean
            If _hostedWidgetContent.Count = 0 Then Return True
            Dim children As New List(Of MASControlBase)(_hostedWidgetContent.Values)
            _hostedWidgetContent.Clear()
            For Each child As MASControlBase In children
                If child Is Nothing Then Continue For
                UnregisterChild(child)
                If disposeChildren Then child.Dispose()
            Next
            _hostedWidgetLifecycleGeneration += 1
            InvalidateVisual()
            Return True
        End Function

        Friend Function CreateHostedWidgetContentSnapshot() As MASHostedContentContractSnapshot
            Dim slots As New List(Of MASHostedContentSlotSnapshot)()
            For Each widget As DashboardWidgetState In _widgets
                If widget Is Nothing Then Continue For
                Dim child As MASControlBase = Nothing
                _hostedWidgetContent.TryGetValue(widget.Key, child)
                slots.Add(MASHostedContentContractPolicy.CreateSnapshot(
                    "dashboardgrid",
                    widget.Key,
                    MASHostedContentSlotKind.DashboardWidget,
                    child,
                    child IsNot Nothing AndAlso child.Visible,
                    If(child Is Nothing, SKRect.Empty, child.BoundsLogical),
                    ResolveHostedContentClip(child),
                    _hostedWidgetLifecycleGeneration))
            Next
            Return New MASHostedContentContractSnapshot("dashboardgrid", _hostedWidgetLifecycleGeneration, slots)
        End Function

        Friend Function HasWidgetHostingContractForTests() As Boolean
            If _widgets.Count = 0 Then Return False
            Dim key As String = _widgets(0).Key
            Dim child As MASControlBase = MASButton.Create("Hosted widget")
            If Not HostWidgetContent(key, child) Then Return False
            PlaceHostedWidgetContent(key, New SKRect(0.0F, 0.0F, 160.0F, 64.0F), 1.0F)
            Dim snapshot As MASHostedContentContractSnapshot = CreateHostedWidgetContentSnapshot()
            Dim hosted As Boolean = snapshot IsNot Nothing AndAlso
                                     snapshot.IsStructurallyValid AndAlso
                                     snapshot.HasHostedSlot(key) AndAlso
                                     snapshot.HasVisibleHostedSlot(key) AndAlso
                                     snapshot.HostedSlotCount >= 1
            Dim removed As Boolean = UnhostWidgetContent(key, disposeChild:=True)
            Dim after As MASHostedContentContractSnapshot = CreateHostedWidgetContentSnapshot()
            Return hosted AndAlso removed AndAlso after IsNot Nothing AndAlso Not after.HasHostedSlot(key)
        End Function

        Private Sub PlaceHostedWidgetContent(widgetKey As String,
                                             boundsPx As SKRect,
                                             dpi As Single)
            Dim key As String = MASDashboardGridPolicy.NormalizeKey(widgetKey, "widget", 1)
            Dim child As MASControlBase = Nothing
            If Not _hostedWidgetContent.TryGetValue(key, child) Then Return
            MASHostedContentContractPolicy.PlaceChild(child, boundsPx, dpi, _widgetsRect)
        End Sub

        Private Shared Function ResolveHostedContentClip(child As MASControlBase) As System.Nullable(Of SKRect)
            If child Is Nothing Then Return Nothing
            Return child.ClipBoundsLogicalInternal
        End Function


#End Region

    End Class

End Namespace
