Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Globalization

Namespace Nexamas.UI.Certification

    ''' <summary>
    ''' Immutable internal proof matrix that keeps Source, Runtime, Package, and Consumer
    ''' certification semantics separate.  This prevents the lightweight Quality Orchestrator
    ''' from producing wording that looks like a full SDK release certificate.
    ''' </summary>
    Friend NotInheritable Class MASCertificationProofMatrix
        Private ReadOnly _nonReleaseableConditions As IReadOnlyList(Of String)

        Friend Sub New(sourceStatus As MASCertificationProofScopeStatus,
                       runtimeStatus As MASCertificationProofScopeStatus,
                       packageStatus As MASCertificationProofScopeStatus,
                       consumerStatus As MASCertificationProofScopeStatus,
                       runMode As String,
                       nonReleaseableConditions As IEnumerable(Of String))
            Me.SourceStatus = sourceStatus
            Me.RuntimeStatus = runtimeStatus
            Me.PackageStatus = packageStatus
            Me.ConsumerStatus = consumerStatus
            Me.RunMode = Normalize(runMode)
            _nonReleaseableConditions = New ReadOnlyCollection(Of String)(NormalizeConditions(nonReleaseableConditions))
        End Sub

        Friend ReadOnly Property SourceStatus As MASCertificationProofScopeStatus
        Friend ReadOnly Property RuntimeStatus As MASCertificationProofScopeStatus
        Friend ReadOnly Property PackageStatus As MASCertificationProofScopeStatus
        Friend ReadOnly Property ConsumerStatus As MASCertificationProofScopeStatus
        Friend ReadOnly Property RunMode As String

        Friend ReadOnly Property NonReleaseableConditions As IReadOnlyList(Of String)
            Get
                Return _nonReleaseableConditions
            End Get
        End Property

        Friend ReadOnly Property SourceCertified As Boolean
            Get
                Return IsPositive(SourceStatus)
            End Get
        End Property

        Friend ReadOnly Property RuntimeCertified As Boolean
            Get
                Return IsPositive(RuntimeStatus)
            End Get
        End Property

        Friend ReadOnly Property PackageCertified As Boolean
            Get
                Return IsPositive(PackageStatus)
            End Get
        End Property

        Friend ReadOnly Property ConsumerCertified As Boolean
            Get
                Return IsPositive(ConsumerStatus)
            End Get
        End Property

        Friend ReadOnly Property HasAnyProof As Boolean
            Get
                Return SourceStatus <> MASCertificationProofScopeStatus.NotRun OrElse
                       RuntimeStatus <> MASCertificationProofScopeStatus.NotRun OrElse
                       PackageStatus <> MASCertificationProofScopeStatus.NotRun OrElse
                       ConsumerStatus <> MASCertificationProofScopeStatus.NotRun
            End Get
        End Property

        Friend ReadOnly Property HasBlockingProof As Boolean
            Get
                Return SourceStatus = MASCertificationProofScopeStatus.Blocked OrElse
                       RuntimeStatus = MASCertificationProofScopeStatus.Blocked OrElse
                       PackageStatus = MASCertificationProofScopeStatus.Blocked OrElse
                       ConsumerStatus = MASCertificationProofScopeStatus.Blocked
            End Get
        End Property

        Friend ReadOnly Property HasMissingRuntimePackageOrConsumerProof As Boolean
            Get
                Return RuntimeStatus = MASCertificationProofScopeStatus.NotRun OrElse
                       PackageStatus = MASCertificationProofScopeStatus.NotRun OrElse
                       ConsumerStatus = MASCertificationProofScopeStatus.NotRun
            End Get
        End Property

        Friend ReadOnly Property HasFullCommercialProof As Boolean
            Get
                Return SourceStatus = MASCertificationProofScopeStatus.Certified AndAlso
                       RuntimeStatus = MASCertificationProofScopeStatus.Certified AndAlso
                       PackageStatus = MASCertificationProofScopeStatus.Certified AndAlso
                       ConsumerStatus = MASCertificationProofScopeStatus.Certified AndAlso
                       NonReleaseableConditions.Count = 0
            End Get
        End Property

        Friend ReadOnly Property Summary As String
            Get
                Dim text As String = "Proof scopes: Source=" & SourceStatus.ToString() &
                    ", Runtime=" & RuntimeStatus.ToString() &
                    ", Package=" & PackageStatus.ToString() &
                    ", Consumer=" & ConsumerStatus.ToString() &
                    "; RunMode=" & If(String.IsNullOrWhiteSpace(RunMode), "Unknown", RunMode) & "."
                If NonReleaseableConditions.Count > 0 Then
                    text &= " Non-releaseable condition(s): " & NonReleaseableConditions.Count.ToString(CultureInfo.InvariantCulture) & "."
                End If
                Return text
            End Get
        End Property

        Friend Shared Function DeclaredOnly() As MASCertificationProofMatrix
            Return New MASCertificationProofMatrix(
                MASCertificationProofScopeStatus.NotRun,
                MASCertificationProofScopeStatus.NotRun,
                MASCertificationProofScopeStatus.NotRun,
                MASCertificationProofScopeStatus.NotRun,
                "DeclaredOnly",
                New String() {"No executable quality proof scope was attached to this manifest."})
        End Function

        Friend Shared Function SourceOnly(sourceStatus As NexamasUICertificationStatus) As MASCertificationProofMatrix
            Dim conditions As New List(Of String) From {
                "Quality Orchestrator is a lightweight source/governance proof only.",
                "Runtime, package, and packed-consumer proofs must come from the quality runner full release path."
            }

            Return New MASCertificationProofMatrix(
                ConvertPlatformStatus(sourceStatus),
                MASCertificationProofScopeStatus.NotRun,
                MASCertificationProofScopeStatus.NotRun,
                MASCertificationProofScopeStatus.NotRun,
                "SourceOrchestratorOnly",
                conditions)
        End Function

        Private Shared Function ConvertPlatformStatus(status As NexamasUICertificationStatus) As MASCertificationProofScopeStatus
            Select Case status
                Case NexamasUICertificationStatus.Certified
                    Return MASCertificationProofScopeStatus.Certified
                Case NexamasUICertificationStatus.CertifiedWithMonitoring, _
                     NexamasUICertificationStatus.EvidenceDeclared, _
                     NexamasUICertificationStatus.SourceCertifiedOnly
                    Return MASCertificationProofScopeStatus.CertifiedWithMonitoring
                Case NexamasUICertificationStatus.Blocked, _
                     NexamasUICertificationStatus.IncompleteGovernance
                    Return MASCertificationProofScopeStatus.Blocked
                Case Else
                    Return MASCertificationProofScopeStatus.NotRun
            End Select
        End Function

        Private Shared Function IsPositive(status As MASCertificationProofScopeStatus) As Boolean
            Return status = MASCertificationProofScopeStatus.Certified OrElse
                   status = MASCertificationProofScopeStatus.CertifiedWithMonitoring
        End Function

        Private Shared Function NormalizeConditions(conditions As IEnumerable(Of String)) As List(Of String)
            Dim result As New List(Of String)()
            If conditions Is Nothing Then Return result

            For Each condition As String In conditions
                Dim normalized As String = Normalize(condition)
                If normalized.Length > 0 AndAlso Not result.Contains(normalized) Then result.Add(normalized)
            Next

            Return result
        End Function

        Private Shared Function Normalize(value As String) As String
            Return If(value, String.Empty).Trim()
        End Function
    End Class

End Namespace
