Option Strict On
Option Explicit On

Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Reflection
Imports Nexamas.UI.Components

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Commercial governance evidence for Friend-only material-region composition. It confirms
    ''' that premium element authors can compose Root/Header/Footer/Toolbar/Viewport from multiple
    ''' official materials without opening new user-facing API or bypassing the Surface gateway.
    ''' </summary>
    Friend NotInheritable Class MASVisualMaterialRegionCompositionAudit
        Private Sub New()
        End Sub

        Friend Shared Function BuildCurrentMaterialRegionComposition() As MASVisualMaterialRegionCompositionReport
            Dim hasFriendOnlyComposition As Boolean = ProbeFriendOnlyCompositionTypes()
            Dim hasSemanticGatewayRoutes As Boolean = ProbeSemanticGatewayRoutes()
            Dim hasImageViewerAuthoringProof As Boolean = ProbeRegionAuthoringPolicy()
            Dim exposesNoPublicRegionMaterialApi As Boolean = ProbeNoPublicRegionMaterialApi()

            Dim status As MASVisualMaterialRegionCompositionStatus = DetermineStatus(
                hasFriendOnlyComposition,
                hasSemanticGatewayRoutes,
                hasImageViewerAuthoringProof,
                exposesNoPublicRegionMaterialApi)

            Return New MASVisualMaterialRegionCompositionReport(
                name:="Nexamas UI Material Region Composition",
                status:=status,
                hasFriendOnlyComposition:=hasFriendOnlyComposition,
                hasSemanticGatewayRoutes:=hasSemanticGatewayRoutes,
                hasImageViewerAuthoringProof:=hasImageViewerAuthoringProof,
                exposesNoPublicRegionMaterialApi:=exposesNoPublicRegionMaterialApi,
                evidence:=Evidence())
        End Function

        Private Shared Function DetermineStatus(hasFriendOnlyComposition As Boolean,
                                                hasSemanticGatewayRoutes As Boolean,
                                                hasImageViewerAuthoringProof As Boolean,
                                                exposesNoPublicRegionMaterialApi As Boolean) As MASVisualMaterialRegionCompositionStatus
            If Not hasFriendOnlyComposition Then Return MASVisualMaterialRegionCompositionStatus.BlockedByMissingFriendComposition
            If Not hasSemanticGatewayRoutes Then Return MASVisualMaterialRegionCompositionStatus.BlockedByMissingSemanticGatewayRoutes
            If Not hasImageViewerAuthoringProof Then Return MASVisualMaterialRegionCompositionStatus.BlockedByMissingImageViewerAuthoringProof
            If Not exposesNoPublicRegionMaterialApi Then Return MASVisualMaterialRegionCompositionStatus.BlockedByPublicRegionApi
            Return MASVisualMaterialRegionCompositionStatus.Closed
        End Function

        Private Shared Function ProbeFriendOnlyCompositionTypes() As Boolean
            Return GetType(MASComponentSurfaceMaterialComposition).IsNotPublic AndAlso
                   GetType(MASComponentSurfaceMaterialBinding).IsNotPublic AndAlso
                   GetType(MASComponentSurfaceRegion).IsNotPublic
        End Function

        Private Shared Function ProbeSemanticGatewayRoutes() As Boolean
            For Each routeName As String In SemanticRouteNames()
                If GetType(MASSurfaceMaterialComponentGateway).GetMethod(
                    routeName,
                    BindingFlags.NonPublic Or BindingFlags.Public Or BindingFlags.Static) Is Nothing Then
                    Return False
                End If
            Next
            Return True
        End Function

        Private Shared Function ProbeRegionAuthoringPolicy() As Boolean
            Dim composition As MASComponentSurfaceMaterialComposition = MASImageViewerSurfacePolicy.CreateComposition()
            If composition Is Nothing Then Return False

            Dim rootBinding As MASComponentSurfaceMaterialBinding = composition.Resolve(MASComponentSurfaceRegion.Root, MASSurfaceMaterialIds.Auto)
            Dim viewportBinding As MASComponentSurfaceMaterialBinding = composition.Resolve(MASComponentSurfaceRegion.Viewport, MASSurfaceMaterialIds.Auto)
            Dim toolbarBinding As MASComponentSurfaceMaterialBinding = composition.Resolve(MASComponentSurfaceRegion.Toolbar, MASSurfaceMaterialIds.Auto)
            Dim footerBinding As MASComponentSurfaceMaterialBinding = composition.Resolve(MASComponentSurfaceRegion.Footer, MASSurfaceMaterialIds.Auto)
            Dim overlayBinding As MASComponentSurfaceMaterialBinding = composition.Resolve(MASComponentSurfaceRegion.Overlay, MASSurfaceMaterialIds.Auto)

            Return rootBinding IsNot Nothing AndAlso rootBinding.IsAuthored AndAlso
                   viewportBinding IsNot Nothing AndAlso viewportBinding.IsAuthored AndAlso
                   toolbarBinding IsNot Nothing AndAlso toolbarBinding.IsAuthored AndAlso
                   footerBinding IsNot Nothing AndAlso footerBinding.IsAuthored AndAlso
                   overlayBinding IsNot Nothing AndAlso overlayBinding.IsAuthored AndAlso
                   composition.HasAnyAuthoredMaterial()
        End Function

        Private Shared Function ProbeNoPublicRegionMaterialApi() As Boolean
            Return HasNoDeclaredPublicMembers(GetType(MASComponentSurfaceMaterialComposition)) AndAlso
                   HasNoDeclaredPublicMembers(GetType(MASComponentSurfaceMaterialBinding)) AndAlso
                   HasNoDeclaredPublicMembers(GetType(MASComponentSurfaceRegion))
        End Function

        Private Shared Function HasNoDeclaredPublicMembers(typeToInspect As System.Type) As Boolean
            If typeToInspect Is Nothing Then Return False
            If typeToInspect.IsNotPublic OrElse typeToInspect.IsNestedAssembly Then Return True

            Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.DeclaredOnly
            Return typeToInspect.GetMethods(flags).Length = 0 AndAlso
                   typeToInspect.GetProperties(flags).Length = 0
        End Function

        Private Shared Function SemanticRouteNames() As IReadOnlyList(Of String)
            Return New ReadOnlyCollection(Of String)(New List(Of String) From {
                "TryDrawComposedCardSurface",
                "TryDrawComposedCardRootSurface",
                "TryDrawComposedCardViewportSurface",
                "TryDrawComposedToolbarSurface",
                "TryDrawComposedMediaStageSurface",
                "TryDrawAuthoredMaterialSurface"})
        End Function

        Private Shared Function SemanticRoutes() As IReadOnlyList(Of String)
            Dim result As New List(Of String)()
            For Each routeName As String In SemanticRouteNames()
                result.Add("MASSurfaceMaterialComponentGateway." & routeName)
            Next
            Return New ReadOnlyCollection(Of String)(result)
        End Function

        Private Shared Function ImageViewerProof() As IReadOnlyList(Of String)
            Return New ReadOnlyCollection(Of String)(New List(Of String) From {
                "MASImageViewer.Root uses MASComponentSurfaceRegion.Root through MASImageViewerSurfacePolicy with authored PlatformDefault",
                "MASImageViewer.Toolbar uses MASComponentSurfaceRegion.Toolbar through MASImageViewerSurfacePolicy with authored MediaCommandRail",
                "MASImageViewer.Viewport uses MASComponentSurfaceRegion.Viewport through MASImageViewerSurfacePolicy with authored FrostedGlass",
                "MASImageViewer.Footer uses MASComponentSurfaceRegion.Footer through MASImageViewerSurfacePolicy with authored MediaFooterChrome",
                "MASImageViewer.Overlay uses MASComponentSurfaceRegion.Overlay through MASImageViewerSurfacePolicy with authored MediaToolbarGlass"})
        End Function

        Private Shared Function Evidence() As IReadOnlyList(Of String)
            Dim result As New List(Of String)()
            result.AddRange(SemanticRoutes())
            result.AddRange(ImageViewerProof())
            result.Add("MASComponentSurfaceMaterialComposition Friend-only type probe")
            result.Add("MASComponentSurfaceMaterialBinding Friend-only type probe")
            result.Add("No user-facing region material properties were added")
            Return New ReadOnlyCollection(Of String)(result)
        End Function
    End Class

End Namespace
