Option Strict On
Option Explicit On

Imports System
Imports System.Linq

Namespace Nexamas.UI.Modules

    ''' <summary>
    ''' Immutable evidence snapshot for the small Plugin / Module System foundation.
    ''' </summary>
    Friend NotInheritable Class MASModuleRegistrySnapshot

        Private ReadOnly _modules As MASModuleDescriptor()
        Private ReadOnly _contributions As MASModuleContribution()

        Friend Sub New(modules As MASModuleDescriptor(),
                       contributions As MASModuleContribution(),
                       sourceName As String,
                       duplicateContributionCount As Integer)
            _modules = If(modules, New MASModuleDescriptor() {}).Where(Function(moduleDescriptor) moduleDescriptor IsNot Nothing).ToArray()
            _contributions = If(contributions, New MASModuleContribution() {}).Where(Function(contribution) contribution IsNot Nothing).ToArray()
            Me.SourceName = MASModuleContribution.NormalizeText(sourceName)
            Me.DuplicateContributionCount = Math.Max(0, duplicateContributionCount)
        End Sub

        Friend ReadOnly Property SourceName As String
        Friend ReadOnly Property DuplicateContributionCount As Integer

        Friend ReadOnly Property Modules As MASModuleDescriptor()
            Get
                Return DirectCast(_modules.Clone(), MASModuleDescriptor())
            End Get
        End Property

        Friend ReadOnly Property Contributions As MASModuleContribution()
            Get
                Return DirectCast(_contributions.Clone(), MASModuleContribution())
            End Get
        End Property

        Friend ReadOnly Property ModuleCount As Integer
            Get
                Return _modules.Length
            End Get
        End Property

        Friend ReadOnly Property ContributionCount As Integer
            Get
                Return _contributions.Length
            End Get
        End Property

        Friend ReadOnly Property PageCount As Integer
            Get
                Return CountKind(MASModuleContributionKind.Page)
            End Get
        End Property

        Friend ReadOnly Property CommandCount As Integer
            Get
                Return CountKind(MASModuleContributionKind.Command)
            End Get
        End Property

        Friend ReadOnly Property SettingsSectionCount As Integer
            Get
                Return CountKind(MASModuleContributionKind.SettingsSection)
            End Get
        End Property

        Friend ReadOnly Property ThemeCount As Integer
            Get
                Return CountKind(MASModuleContributionKind.Theme)
            End Get
        End Property

        Friend ReadOnly Property ToolCount As Integer
            Get
                Return CountKind(MASModuleContributionKind.Tool)
            End Get
        End Property

        Friend ReadOnly Property HasNoDuplicateContributionKeys As Boolean
            Get
                Return DuplicateContributionCount = 0 AndAlso
                       _contributions.Select(Function(contribution) contribution.Key).Distinct(StringComparer.OrdinalIgnoreCase).Count() = _contributions.Length
            End Get
        End Property

        Friend ReadOnly Property HasValidModules As Boolean
            Get
                Return _modules.Length > 0 AndAlso _modules.All(Function(moduleDescriptor) moduleDescriptor.IsValid AndAlso moduleDescriptor.HasInternallyConsistentContributions)
            End Get
        End Property

        Friend ReadOnly Property HasValidContributions As Boolean
            Get
                Return _contributions.Length > 0 AndAlso _contributions.All(Function(contribution) contribution.IsValid)
            End Get
        End Property

        Friend ReadOnly Property HasPageCommandSettingsThemeToolCoverage As Boolean
            Get
                Return PageCount > 0 AndAlso CommandCount > 0 AndAlso SettingsSectionCount > 0 AndAlso ThemeCount > 0 AndAlso ToolCount > 0
            End Get
        End Property

        Friend ReadOnly Property RoutesCommandsThroughCommandActionSystem As Boolean
            Get
                Return _contributions.All(Function(contribution) contribution.IsCommandRouteOwnedByCommandActionSystem)
            End Get
        End Property

        Friend ReadOnly Property Status As MASModuleRegistrationStatus
            Get
                If ModuleCount = 0 AndAlso ContributionCount = 0 Then Return MASModuleRegistrationStatus.Empty
                If DuplicateContributionCount > 0 OrElse Not HasNoDuplicateContributionKeys Then Return MASModuleRegistrationStatus.DuplicateContribution
                If Not HasValidModules Then Return MASModuleRegistrationStatus.InvalidModule
                If Not HasValidContributions Then Return MASModuleRegistrationStatus.InvalidContribution
                Return MASModuleRegistrationStatus.Ready
            End Get
        End Property

        Friend ReadOnly Property ReadyForSmallModuleSystem As Boolean
            Get
                Return Status = MASModuleRegistrationStatus.Ready AndAlso
                       HasPageCommandSettingsThemeToolCoverage AndAlso
                       RoutesCommandsThroughCommandActionSystem
            End Get
        End Property

        Friend Function CountKind(kind As MASModuleContributionKind) As Integer
            Return _contributions.Where(Function(contribution) contribution.Kind = kind).Count()
        End Function

    End Class

End Namespace
