Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Final broad-surface switch-readiness audit. It proves the "one button" internal material
    ''' switch is centralized and that the default switch state is inert, so current visuals are not
    ''' changed until Theme Studio or Showcase deliberately selects another profile/material.
    ''' </summary>
    Friend NotInheritable Class MASVisualSurfaceMaterialSwitchReadinessAudit
        Private Sub New()
        End Sub

        Friend Shared Function BuildCurrentSurfaceMaterialSwitchReadiness() As MASVisualSurfaceMaterialSwitchReadinessReport
            Dim hasRuntimeSwitchGateway As Boolean = ProbeRuntimeSwitchGateway()
            Dim defaultStateIsInert As Boolean = Not MASSurfaceMaterialRuntimeSwitch.IsActive AndAlso
                                                  MASSurfaceMaterialRuntimeSwitch.IsSwitchableDefaultProfileId(MASSurfaceMaterialRuntimeSwitch.ActiveProfileId) AndAlso
                                                  MASSurfaceMaterialRuntimeSwitch.IsSwitchableDefaultMaterialKey(MASSurfaceMaterialRuntimeSwitch.ActiveMaterialKey)
            Dim slotResolverUsesRuntimeSwitch As Boolean = ProbeSlotResolverScopedSwitch()
            Dim runtimeSurfaceUsesRuntimeSwitch As Boolean = ProbeRuntimeSurfaceScopedSwitch()
            Dim frameBackedSurfacesUseRuntimeSwitchWhenActive As Boolean = ProbeFrameBackedScopedSwitch()
            Dim explicitMaterialOverridesStayExplicit As Boolean = ProbeExplicitMaterialOverrideProtection()

            Dim status As MASVisualSurfaceMaterialSwitchReadinessStatus = DetermineStatus(
                hasRuntimeSwitchGateway,
                defaultStateIsInert,
                slotResolverUsesRuntimeSwitch,
                runtimeSurfaceUsesRuntimeSwitch,
                frameBackedSurfacesUseRuntimeSwitchWhenActive,
                explicitMaterialOverridesStayExplicit)

            Return New MASVisualSurfaceMaterialSwitchReadinessReport(
                name:="Nexamas UI Surface Material Switch Readiness",
                status:=status,
                hasRuntimeSwitchGateway:=hasRuntimeSwitchGateway,
                defaultStateIsInert:=defaultStateIsInert,
                slotResolverUsesRuntimeSwitch:=slotResolverUsesRuntimeSwitch,
                runtimeSurfaceUsesRuntimeSwitch:=runtimeSurfaceUsesRuntimeSwitch,
                frameBackedSurfacesUseRuntimeSwitchWhenActive:=frameBackedSurfacesUseRuntimeSwitchWhenActive,
                explicitMaterialOverridesStayExplicit:=explicitMaterialOverridesStayExplicit,
                switchableSurfaceFamilies:=SwitchableSurfaceFamilies(),
                frameBackedSwitchConsumers:=FrameBackedSwitchConsumers())
        End Function

        Private Shared Function DetermineStatus(hasRuntimeSwitchGateway As Boolean,
                                                defaultStateIsInert As Boolean,
                                                slotResolverUsesRuntimeSwitch As Boolean,
                                                runtimeSurfaceUsesRuntimeSwitch As Boolean,
                                                frameBackedSurfacesUseRuntimeSwitchWhenActive As Boolean,
                                                explicitMaterialOverridesStayExplicit As Boolean) As MASVisualSurfaceMaterialSwitchReadinessStatus
            If Not hasRuntimeSwitchGateway Then Return MASVisualSurfaceMaterialSwitchReadinessStatus.BlockedByMissingRuntimeSwitch
            If Not defaultStateIsInert Then Return MASVisualSurfaceMaterialSwitchReadinessStatus.BlockedByNonInertDefault
            If Not slotResolverUsesRuntimeSwitch Then Return MASVisualSurfaceMaterialSwitchReadinessStatus.BlockedBySlotResolverBypass
            If Not runtimeSurfaceUsesRuntimeSwitch Then Return MASVisualSurfaceMaterialSwitchReadinessStatus.BlockedByRuntimeSurfaceBypass
            If Not frameBackedSurfacesUseRuntimeSwitchWhenActive Then Return MASVisualSurfaceMaterialSwitchReadinessStatus.BlockedByFrameBackedSurfaceBypass
            If Not explicitMaterialOverridesStayExplicit Then Return MASVisualSurfaceMaterialSwitchReadinessStatus.BlockedByExplicitOverrideRegression
            Return MASVisualSurfaceMaterialSwitchReadinessStatus.Closed
        End Function

        Private Shared Function ProbeRuntimeSwitchGateway() As Boolean
            Dim scope As IDisposable = MASSurfaceMaterialRuntimeSwitch.BeginMaterialScope(MASSurfaceMaterialIds.CrystalIce)

            Try
                Return scope IsNot Nothing AndAlso
                       MASSurfaceMaterialRuntimeSwitch.IsActive AndAlso
                       String.Equals(MASSurfaceMaterialRuntimeSwitch.ActiveMaterialKey, MASSurfaceMaterialIds.CrystalIce, StringComparison.OrdinalIgnoreCase)
            Finally
                If scope IsNot Nothing Then scope.Dispose()
            End Try
        End Function

        Private Shared Function ProbeSlotResolverScopedSwitch() As Boolean
            Dim scope As IDisposable = MASSurfaceMaterialRuntimeSwitch.BeginMaterialScope(MASSurfaceMaterialIds.CrystalIce)

            Try
                Dim route As MASSurfaceMaterialSlotRoute = MASSurfaceMaterialSlotResolver.ResolveMaterialKey(
                    consumerKind:=MASSurfaceTreatmentConsumerKind.CardSurface,
                    materialKey:=MASSurfaceMaterialIds.Auto,
                    slot:=MASSurfaceSlot.Root,
                    fallbackRole:=MASSurfaceRole.Card,
                    frameStrength:=MASSurfaceFrameStrength.Level3)

                Return route IsNot Nothing AndAlso
                       String.Equals(route.MaterialKey, MASSurfaceMaterialIds.CrystalIce, StringComparison.OrdinalIgnoreCase)
            Finally
                If scope IsNot Nothing Then scope.Dispose()
            End Try
        End Function

        Private Shared Function ProbeRuntimeSurfaceScopedSwitch() As Boolean
            Dim scope As IDisposable = MASSurfaceMaterialRuntimeSwitch.BeginMaterialScope(MASSurfaceMaterialIds.CrystalIce)

            Try
                Dim resolvedKey As String = MASSurfaceTreatmentRuntimeMaterialBody.ResolveMaterialKey(
                    consumerKind:=MASSurfaceTreatmentConsumerKind.CardSurface,
                    materialKey:=MASSurfaceMaterialIds.Auto,
                    requestedFrameStrength:=MASSurfaceFrameStrength.Level3,
                    hasExplicitMaterialOverride:=False)

                Return String.Equals(resolvedKey, MASSurfaceMaterialIds.CrystalIce, StringComparison.OrdinalIgnoreCase)
            Finally
                If scope IsNot Nothing Then scope.Dispose()
            End Try
        End Function

        Private Shared Function ProbeFrameBackedScopedSwitch() As Boolean
            Dim scope As IDisposable = MASSurfaceMaterialRuntimeSwitch.BeginMaterialScope(MASSurfaceMaterialIds.CrystalIce)

            Try
                Dim materialKey As String = String.Empty
                Dim frameKey As String = String.Empty
                Return MASSurfaceMaterialRuntimeSwitch.TryResolveActiveMaterialForImplicit(
                    requestedMaterialKey:=MASSurfaceMaterialIds.Auto,
                    hasExplicitMaterialOverride:=False,
                    resolvedMaterialKey:=materialKey,
                    resolvedFrameKey:=frameKey) AndAlso
                    String.Equals(materialKey, MASSurfaceMaterialIds.CrystalIce, StringComparison.OrdinalIgnoreCase) AndAlso
                    frameKey.Length > 0
            Finally
                If scope IsNot Nothing Then scope.Dispose()
            End Try
        End Function

        Private Shared Function ProbeExplicitMaterialOverrideProtection() As Boolean
            Dim scope As IDisposable = MASSurfaceMaterialRuntimeSwitch.BeginMaterialScope(MASSurfaceMaterialIds.CrystalIce)

            Try
                Dim resolvedKey As String = MASSurfaceMaterialRuntimeSwitch.ResolveRuntimeMaterialKey(
                    consumerKind:=MASSurfaceTreatmentConsumerKind.CardSurface,
                    requestedMaterialKey:=MASSurfaceMaterialIds.SoftMist,
                    hasExplicitMaterialOverride:=True,
                    slot:=MASSurfaceSlot.Root)

                Return String.Equals(resolvedKey, MASSurfaceMaterialIds.SoftMist, StringComparison.OrdinalIgnoreCase)
            Finally
                If scope IsNot Nothing Then scope.Dispose()
            End Try
        End Function

        Private Shared Function SwitchableSurfaceFamilies() As IReadOnlyList(Of String)
            Return New ReadOnlyCollection(Of String)(New List(Of String) From {
                "Card primitive broad surfaces",
                "Default/public surface material consumers",
                "Direct runtime container surfaces",
                "Frame-backed list/menu/tree/toast surfaces",
                "Acrylic primitive shell surfaces",
                "Semantic component surface gateway routes"
            })
        End Function

        Private Shared Function FrameBackedSwitchConsumers() As IReadOnlyList(Of String)
            Return New ReadOnlyCollection(Of String)(New List(Of String) From {
                "MASListBox",
                "MASListView",
                "MASTreeRenderer",
                "MASDropDownListFloatContent",
                "DropDownMenuRenderer",
                "MASToastRenderer"
            })
        End Function
    End Class

End Namespace
