Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASMasterDetailView

#Region "Friend hosted detail content contract"

        Private ReadOnly _hostedDetailContent As New Dictionary(Of String, MASControlBase)(StringComparer.Ordinal)
        Private _hostedDetailLifecycleGeneration As Integer

        Friend Function HostDetailContent(itemKey As String,
                                          child As MASControlBase) As Boolean
            If child Is Nothing Then Return False
            Dim key As String = MASMasterDetailViewPolicy.NormalizeKey(itemKey, "item", 1)
            If FindItemIndex(key) < 0 Then Return False

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

            RegisterChild(child)
            If String.IsNullOrWhiteSpace(child.Name) Then child.Name = "MasterDetailHost_" & key
            _hostedDetailContent.Add(key, child)
            _hostedDetailLifecycleGeneration += 1
            InvalidateVisual()
            Return True
        End Function

        Friend Function UnhostDetailContent(itemKey As String,
                                            Optional disposeChild As Boolean = False) As Boolean
            Dim key As String = MASMasterDetailViewPolicy.NormalizeKey(itemKey, "item", 1)
            Dim child As MASControlBase = Nothing
            If Not _hostedDetailContent.TryGetValue(key, child) Then Return False
            _hostedDetailContent.Remove(key)
            If child IsNot Nothing Then
                UnregisterChild(child)
                If disposeChild Then child.Dispose()
            End If
            _hostedDetailLifecycleGeneration += 1
            InvalidateVisual()
            Return True
        End Function

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

        Friend Function CreateHostedDetailContentSnapshot() As MASHostedContentContractSnapshot
            Dim slots As New List(Of MASHostedContentSlotSnapshot)()
            For Each pair As KeyValuePair(Of String, MASControlBase) In _hostedDetailContent
                Dim child As MASControlBase = pair.Value
                slots.Add(MASHostedContentContractPolicy.CreateSnapshot(
                    "masterdetail",
                    pair.Key,
                    MASHostedContentSlotKind.MasterDetailDetail,
                    child,
                    String.Equals(pair.Key, SelectedItemKey, StringComparison.Ordinal) AndAlso child IsNot Nothing AndAlso child.Visible,
                    If(child Is Nothing, SKRect.Empty, child.BoundsLogical),
                    ResolveHostedContentClip(child),
                    _hostedDetailLifecycleGeneration))
            Next
            Return New MASHostedContentContractSnapshot("masterdetail", _hostedDetailLifecycleGeneration, slots)
        End Function

        Friend Function HasDetailHostingContractForTests() As Boolean
            If _items.Count = 0 Then Return False
            Dim key As String = _items(0).Key
            Dim child As MASControlBase = MASButton.Create("Detail host")
            If Not HostDetailContent(key, child) Then Return False
            SelectItem(key)
            PlaceMasterDetailHostedDetailContent(key, New SKRect(0.0F, 0.0F, 180.0F, 90.0F), 1.0F, True)
            Dim snapshot As MASHostedContentContractSnapshot = CreateHostedDetailContentSnapshot()
            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 = UnhostDetailContent(key, disposeChild:=True)
            Dim after As MASHostedContentContractSnapshot = CreateHostedDetailContentSnapshot()
            Return hosted AndAlso removed AndAlso after IsNot Nothing AndAlso after.HostedSlotCount = 0
        End Function

        Private Sub PlaceMasterDetailHostedDetailContent(itemKey As String,
                                                        boundsPx As SKRect,
                                                        dpi As Single,
                                                        isVisible As Boolean)
            Dim key As String = MASMasterDetailViewPolicy.NormalizeKey(itemKey, "item", 1)
            For Each pair As KeyValuePair(Of String, MASControlBase) In _hostedDetailContent
                Dim child As MASControlBase = pair.Value
                If child Is Nothing Then Continue For
                If Not String.Equals(pair.Key, key, StringComparison.Ordinal) OrElse Not isVisible Then
                    child.Visible = False
                    Continue For
                End If
                MASHostedContentContractPolicy.PlaceChild(child, boundsPx, dpi, _detailRect)
            Next
        End Sub

        Private Sub HideAllHostedDetailContent()
            For Each child As MASControlBase In _hostedDetailContent.Values
                If child IsNot Nothing Then child.Visible = False
            Next
        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
