Option Strict On
Option Explicit On

Imports System
Imports System.Linq

Namespace Nexamas.UI.DataBinding

    ''' <summary>
    ''' Immutable snapshot proving binding sessions have disposal, unsubscribe, weak-command, loop-guard, and reflection-cache evidence.
    ''' </summary>
    Friend NotInheritable Class MASViewModelBindingLifecycleSnapshot

        Private ReadOnly _records As MASViewModelBindingLifecycleRecord()

        Friend Sub New(records As MASViewModelBindingLifecycleRecord(),
                       bindingCount As Integer,
                       commandBindingCount As Integer,
                       isDisposed As Boolean,
                       sourceNotificationActive As Boolean,
                       blockedReentrantRefreshCount As Integer,
                       blockedReentrantPushCount As Integer,
                       reflectionCacheEntryCount As Integer,
                       reflectionCacheHitCount As Integer,
                       reflectionCacheMissCount As Integer)
            _records = If(records, New MASViewModelBindingLifecycleRecord() {}).Where(Function(record) record IsNot Nothing).ToArray()
            Me.BindingCount = Math.Max(0, bindingCount)
            Me.CommandBindingCount = Math.Max(0, commandBindingCount)
            Me.IsDisposed = isDisposed
            Me.SourceNotificationActive = sourceNotificationActive
            Me.BlockedReentrantRefreshCount = Math.Max(0, blockedReentrantRefreshCount)
            Me.BlockedReentrantPushCount = Math.Max(0, blockedReentrantPushCount)
            Me.ReflectionCacheEntryCount = Math.Max(0, reflectionCacheEntryCount)
            Me.ReflectionCacheHitCount = Math.Max(0, reflectionCacheHitCount)
            Me.ReflectionCacheMissCount = Math.Max(0, reflectionCacheMissCount)
        End Sub

        Friend ReadOnly Property Records As MASViewModelBindingLifecycleRecord()
            Get
                Return DirectCast(_records.Clone(), MASViewModelBindingLifecycleRecord())
            End Get
        End Property

        Friend ReadOnly Property BindingCount As Integer
        Friend ReadOnly Property CommandBindingCount As Integer
        Friend ReadOnly Property IsDisposed As Boolean
        Friend ReadOnly Property SourceNotificationActive As Boolean
        Friend ReadOnly Property BlockedReentrantRefreshCount As Integer
        Friend ReadOnly Property BlockedReentrantPushCount As Integer
        Friend ReadOnly Property ReflectionCacheEntryCount As Integer
        Friend ReadOnly Property ReflectionCacheHitCount As Integer
        Friend ReadOnly Property ReflectionCacheMissCount As Integer

        Friend ReadOnly Property RecordCount As Integer
            Get
                Return _records.Length
            End Get
        End Property

        Friend ReadOnly Property HasDisposableSession As Boolean
            Get
                Return _records.Any(Function(record) record.Status = MASViewModelBindingLifecycleStatus.Active OrElse
                                                    record.Status = MASViewModelBindingLifecycleStatus.Disposed)
            End Get
        End Property

        Friend ReadOnly Property HasSourceSubscriptionLifecycle As Boolean
            Get
                Return _records.Any(Function(record) record.IsSourceSubscriptionEvidence)
            End Get
        End Property

        Friend ReadOnly Property HasWeakCommandBindingLeases As Boolean
            Get
                If CommandBindingCount = 0 Then Return False
                Return _records.Any(Function(record) record.IsCommandLifecycleEvidence) AndAlso
                       _records.Where(Function(record) record.CommandId.Length > 0).All(Function(record) record.UsesWeakSourceReference AndAlso record.CanRelease)
            End Get
        End Property

        Friend ReadOnly Property HasLoopGuardEvidence As Boolean
            Get
                Return _records.Any(Function(record) record.IsLoopGuardEvidence)
            End Get
        End Property

        Friend ReadOnly Property HasReflectionCacheEvidence As Boolean
            Get
                Return _records.Any(Function(record) record.IsReflectionCacheEvidence) AndAlso ReflectionCacheMissCount >= 0 AndAlso ReflectionCacheHitCount >= 0
            End Get
        End Property

        Friend ReadOnly Property HasNoActiveCommandLeasesAfterDispose As Boolean
            Get
                If Not IsDisposed Then Return True
                Return Not SourceNotificationActive AndAlso _records.Where(Function(record) record.CommandId.Length > 0).All(Function(record) record.Status = MASViewModelBindingLifecycleStatus.CommandReleased)
            End Get
        End Property

        Friend ReadOnly Property ReadyForLifecycleHardening As Boolean
            Get
                Return HasDisposableSession AndAlso
                       HasSourceSubscriptionLifecycle AndAlso
                       HasWeakCommandBindingLeases AndAlso
                       HasLoopGuardEvidence AndAlso
                       HasReflectionCacheEvidence AndAlso
                       HasNoActiveCommandLeasesAfterDispose
            End Get
        End Property

    End Class

End Namespace
