Option Strict On
Option Explicit On

Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Friend-only readiness facts for the official ImageViewer control. This manifest documents
    ''' that the control owns visual viewing, transform commands, and synchronous transformed export
    ''' while file picking, metadata, galleries, storage prompts, and background work remain outside.
    ''' </summary>
    Friend NotInheritable Class MASImageViewerReadinessManifest
        Private Sub New(status As MASImageViewerReadinessStatus,
                        hasArchitectureRegistration As Boolean,
                        hasTransformSurface As Boolean,
                        hasExportBoundary As Boolean,
                        hasDedicatedImageSurface As Boolean,
                        hasMASOwnedSurfaceMaterials As Boolean,
                        hasNoParallelImageServicePath As Boolean,
                        hasNoRunnerOrBackgroundJobPath As Boolean,
                        hasMouseFocusRingSuppressed As Boolean,
                        hasPremiumDashboardComposition As Boolean,
                        hasMediaLayoutArchitecture As Boolean,
                        surfaceContractReport As MASImageViewerSurfaceContractReport)
            Me.Status = status
            Me.HasArchitectureRegistration = hasArchitectureRegistration
            Me.HasTransformSurface = hasTransformSurface
            Me.HasExportBoundary = hasExportBoundary
            Me.HasDedicatedImageSurface = hasDedicatedImageSurface
            Me.HasMASOwnedSurfaceMaterials = hasMASOwnedSurfaceMaterials
            Me.HasNoParallelImageServicePath = hasNoParallelImageServicePath
            Me.HasNoRunnerOrBackgroundJobPath = hasNoRunnerOrBackgroundJobPath
            Me.HasMouseFocusRingSuppressed = hasMouseFocusRingSuppressed
            Me.HasPremiumDashboardComposition = hasPremiumDashboardComposition
            Me.HasMediaLayoutArchitecture = hasMediaLayoutArchitecture
            Me.SurfaceContractReport = surfaceContractReport
        End Sub

        Friend ReadOnly Property Status As MASImageViewerReadinessStatus
        Friend ReadOnly Property HasArchitectureRegistration As Boolean
        Friend ReadOnly Property HasTransformSurface As Boolean
        Friend ReadOnly Property HasExportBoundary As Boolean
        Friend ReadOnly Property HasDedicatedImageSurface As Boolean
        Friend ReadOnly Property HasMASOwnedSurfaceMaterials As Boolean
        Friend ReadOnly Property HasNoParallelImageServicePath As Boolean
        Friend ReadOnly Property HasNoRunnerOrBackgroundJobPath As Boolean
        Friend ReadOnly Property HasMouseFocusRingSuppressed As Boolean
        Friend ReadOnly Property HasPremiumDashboardComposition As Boolean
        Friend ReadOnly Property HasMediaLayoutArchitecture As Boolean
        Friend ReadOnly Property SurfaceContractReport As MASImageViewerSurfaceContractReport

        Friend Shared Function CreateCurrent() As MASImageViewerReadinessManifest
            Dim hasArchitecture As Boolean = HasOfficialMediaArchitectureRegistration()
            Dim hasTransforms As Boolean = True
            Dim hasExport As Boolean = True
            Dim dedicatedImageSurface As Boolean = MASImageViewerVisualPolicy.HasDedicatedImageSurface
            Dim masOwnedSurfaceMaterials As Boolean = MASImageViewerVisualPolicy.HasMASOwnedSurfaceMaterials
            Dim noParallelImageService As Boolean = MASImageViewerVisualPolicy.HasNoParallelImageServicePath
            Dim noRunner As Boolean = MASImageViewerVisualPolicy.HasNoRunnerOrBackgroundJobPath
            Dim mouseFocusRingSuppressed As Boolean = MASImageViewerVisualPolicy.HasMouseFocusRingSuppressed()
            Dim premiumDashboardComposition As Boolean = MASImageViewerVisualPolicy.HasPremiumDashboardComposition()
            Dim mediaLayoutArchitecture As Boolean = HasReusableMediaLayoutArchitecture()
            Dim surfaceContractReport As MASImageViewerSurfaceContractReport = MASImageViewerSurfaceContractAudit.BuildCurrentSurfaceContract()
            Dim surfaceContractClosed As Boolean = surfaceContractReport IsNot Nothing AndAlso surfaceContractReport.IsClosed
            Dim status As MASImageViewerReadinessStatus = ResolveStatus(hasArchitecture, hasTransforms, hasExport, dedicatedImageSurface, masOwnedSurfaceMaterials, noParallelImageService, noRunner, mouseFocusRingSuppressed, premiumDashboardComposition, mediaLayoutArchitecture, surfaceContractClosed)
            Return New MASImageViewerReadinessManifest(status, hasArchitecture, hasTransforms, hasExport, dedicatedImageSurface, masOwnedSurfaceMaterials, noParallelImageService, noRunner, mouseFocusRingSuppressed, premiumDashboardComposition, mediaLayoutArchitecture, surfaceContractReport)
        End Function

        Private Shared Function HasOfficialMediaArchitectureRegistration() As Boolean
            Dim descriptor As MASComponentDescriptor = Nothing

            For Each candidate As MASComponentDescriptor In MASComponentRegistry.Components
                If candidate Is Nothing Then Continue For
                If candidate.ComponentType Is GetType(MASImageViewer) Then
                    descriptor = candidate
                    Exit For
                End If
            Next

            If descriptor Is Nothing Then Return False
            If descriptor.Category <> MASComponentCategory.Control Then Return False
            If Not descriptor.ControlKind.HasValue Then Return False
            If descriptor.ControlKind.Value <> CommonEnums.ControlKind.ImageViewer Then Return False
            If descriptor.SurfaceFamily <> CommonEnums.SurfaceFamily.Media Then Return False
            If descriptor.MaterialRole <> MASMaterialRole.Panel Then Return False
            If descriptor.InteractionRole <> MASInteractionRole.Composite Then Return False
            If descriptor.ShadowRole <> MASShadowRole.Floating Then Return False
            If descriptor.RadiusRole <> MASRadiusRole.SurfaceFamily Then Return False
            If descriptor.TypographyRole <> MASTypographyRole.Body Then Return False
            If descriptor.ThemeSurfaceRole <> NexamasUISurfaceRole.Panel Then Return False
            If descriptor.ThemeColorRole <> NexamasUIColorRole.TextBody Then Return False
            If descriptor.ThemeStateRole <> NexamasUIStateRole.Interactive Then Return False
            If descriptor.InputRole <> MASInputRole.PointerAndKeyboard Then Return False
            If descriptor.FocusRole <> MASFocusRole.Focusable Then Return False
            If Not MASRadiusContractRegistry.IsSupported(CommonEnums.SurfaceFamily.Media) Then Return False
            If SurfaceFamilyRadiusProfiles.RadiusScaleForFamily(CommonEnums.SurfaceFamily.Media, RadiusLayer.Surface) <> RadiusScale.Mm Then Return False
            If SurfaceFamilyRadiusProfiles.RadiusScaleForFamily(CommonEnums.SurfaceFamily.Media, RadiusLayer.Shadow) <> RadiusScale.Mm Then Return False
            If Not MASShadowContractRegistry.IsSupported(MASShadowRole.Floating, CommonEnums.SurfaceFamily.Media) Then Return False
            If Not HasUsableMediaFloatingShadowProfile() Then Return False
            If Not MASInteractionContractRegistry.IsSupported(CommonEnums.SurfaceFamily.Media) Then Return False
            If Not HasPanelShellOuterChromeRelation() Then Return False
            If Not HasPanelShellOuterChromeSpec() Then Return False

            Return True
        End Function

        Private Shared Function HasPanelShellOuterChromeRelation() As Boolean
            Dim provider As New MASMediaComponentRelationProvider()

            For Each relation As MASComponentRelationDeclaration In provider.GetRelations()
                If relation Is Nothing Then Continue For
                If relation.SourceType Is GetType(MASImageViewer) AndAlso
                   relation.TargetType Is GetType(MASPanelShellContract) AndAlso
                   relation.Kind = MASComponentRelationKind.Uses Then
                    Return True
                End If
            Next

            Return False
        End Function

        Private Shared Function HasPanelShellOuterChromeSpec() As Boolean
            Dim bounds As New SKRect(0.0F, 0.0F, 920.0F, 600.0F)
            Dim shellBounds As New SKRect(MediaContainerTokens.PanelShellHostInsetDip,
                                          MediaContainerTokens.PanelShellHostInsetDip,
                                          bounds.Right - MediaContainerTokens.PanelShellHostInsetDip,
                                          bounds.Bottom - MediaContainerTokens.PanelShellHostInsetDip)
            Dim spec As MASPanelShellSpec = MASPanelShellSpec.Create(shellBounds).
                WithoutHeader().
                WithDensity(MASPanelShellDensity.Normal).
                WithPadding(MediaContainerTokens.PanelShellContentPaddingDip).
                WithStrengths(
                    border:=MASPanelShellStrength.Level5,
                    surface:=MASPanelShellStrength.Level5).
                WithSurfaceMaterialKey(MASImageViewerSurfacePolicy.ResolveRootMaterialKey()).
                Build()

            Dim result As MASPanelShellResult = MASPanelShellRenderer.Measure(1.0F, spec)
            If result Is Nothing Then Return False
            If result.BaseRectPx.Width <= 1.0F OrElse result.BaseRectPx.Height <= 1.0F Then Return False
            If result.HasHeader Then Return False
            If result.ContentRectPx.Width <= 1.0F OrElse result.ContentRectPx.Height <= 1.0F Then Return False
            If Math.Abs(result.BaseRectPx.Left - MediaContainerTokens.PanelShellHostInsetDip) > 0.51F Then Return False
            If Math.Abs(result.ContentRectPx.Left - (MediaContainerTokens.PanelShellHostInsetDip + MediaContainerTokens.PanelShellContentPaddingDip)) > 0.51F Then Return False
            Return result.RadiusPx > 0.0F
        End Function

        Private Shared Function HasUsableMediaFloatingShadowProfile() As Boolean
            Dim spec As MASLayeredShadowSpec =
                MASShadowResolver.ResolveLayered(CommonEnums.SurfaceFamily.Media, MASShadowRole.Floating)

            Return spec.SigmaA_Dip > 0.0F AndAlso _
                   spec.AlphaA > 0 AndAlso _
                   spec.SigmaB_Dip > 0.0F AndAlso _
                   spec.AlphaB > 0
        End Function

        Private Shared Function HasReusableMediaLayoutArchitecture() As Boolean
            Dim bounds As New SKRect(0.0F, 0.0F, 920.0F, 600.0F)
            Dim shellBounds As New SKRect(MediaContainerTokens.PanelShellHostInsetDip,
                                          MediaContainerTokens.PanelShellHostInsetDip,
                                          bounds.Right - MediaContainerTokens.PanelShellHostInsetDip,
                                          bounds.Bottom - MediaContainerTokens.PanelShellHostInsetDip)
            Dim shellSpec As MASPanelShellSpec = MASPanelShellSpec.Create(shellBounds).
                WithoutHeader().
                WithPadding(MediaContainerTokens.PanelShellContentPaddingDip).
                WithSurfaceMaterialKey(MASImageViewerSurfacePolicy.ResolveRootMaterialKey()).
                Build()
            Dim shellResult As MASPanelShellResult = MASPanelShellRenderer.Measure(1.0F, shellSpec)
            If shellResult Is Nothing OrElse shellResult.ContentRectPx.Width <= 1.0F OrElse shellResult.ContentRectPx.Height <= 1.0F Then Return False

            Dim plan As MASMediaContainerLayoutPlan =
                MASMediaContainerLayoutResolver.Resolve(bounds:=shellResult.ContentRectPx,
                                                        dpi:=1.0F,
                                                        toolbarChromeAllowed:=True,
                                                        reserveToolbarChrome:=True,
                                                        showFooter:=True,
                                                        toolbarActionCount:=7)

            If plan.Surface.Width <= 1.0F OrElse plan.Surface.Height <= 1.0F Then Return False
            If plan.PreviewFrame.Width <= 1.0F OrElse plan.PreviewFrame.Height <= 1.0F Then Return False
            If plan.PreviewFrame.Left <= plan.Surface.Left + 0.51F Then Return False
            If plan.PreviewFrame.Bottom >= plan.Surface.Bottom - 0.51F Then Return False
            If Math.Abs(plan.Surface.Left - shellResult.ContentRectPx.Left) > 0.01F Then Return False
            If Math.Abs(plan.Surface.Top - shellResult.ContentRectPx.Top) > 0.01F Then Return False
            If Math.Abs(plan.Surface.Right - shellResult.ContentRectPx.Right) > 0.01F Then Return False
            If Math.Abs(plan.Surface.Bottom - shellResult.ContentRectPx.Bottom) > 0.01F Then Return False
            If plan.Toolbar.Height <= 1.0F OrElse plan.Footer.Height <= 1.0F Then Return False
            If plan.Stage.Height <= 1.0F OrElse plan.Viewport.Height <= 1.0F Then Return False
            If Math.Abs(plan.Toolbar.Height - MediaToolbarTokens.HeightDip) > 0.01F Then Return False
            If Math.Abs(plan.Footer.Height - MediaFooterTokens.HeightDip) > 0.01F Then Return False
            If Math.Abs(plan.Toolbar.Top - plan.Surface.Top) > 0.01F Then Return False
            If plan.Toolbar.Bottom > plan.PreviewFrame.Top - 0.51F Then Return False
            If plan.Footer.Bottom > plan.PreviewFrame.Bottom + 0.51F Then Return False
            If plan.Stage.Left < plan.PreviewFrame.Left - 0.51F OrElse plan.Stage.Right > plan.PreviewFrame.Right + 0.51F Then Return False

            Dim content As SKRect = MASMediaViewportLayoutResolver.ResolveContentRect(plan.Viewport, 1.0F)
            If content.Width <= 1.0F OrElse content.Height <= 1.0F Then Return False

            Dim footer As MASMediaFooterLayoutPlan = MASMediaFooterLayoutResolver.Resolve(plan.Footer, 1.0F)
            If footer.IconChip.Width <= 1.0F OrElse footer.ZoomBadge.Width <= 1.0F Then Return False
            If footer.TitleText.Width <= 1.0F OrElse footer.MetadataText.Width <= 1.0F Then Return False

            Return True
        End Function

        Private Shared Function ResolveStatus(hasArchitectureRegistration As Boolean,
                                              hasTransformSurface As Boolean,
                                              hasExportBoundary As Boolean,
                                              hasDedicatedImageSurface As Boolean,
                                              hasMASOwnedSurfaceMaterials As Boolean,
                                              hasNoParallelImageServicePath As Boolean,
                                              hasNoRunnerOrBackgroundJobPath As Boolean,
                                              hasMouseFocusRingSuppressed As Boolean,
                                              hasPremiumDashboardComposition As Boolean,
                                              hasMediaLayoutArchitecture As Boolean,
                                              hasImageViewerSurfaceContract As Boolean) As MASImageViewerReadinessStatus
            If Not hasArchitectureRegistration Then Return MASImageViewerReadinessStatus.MissingArchitectureRegistration
            If Not hasTransformSurface Then Return MASImageViewerReadinessStatus.MissingTransformSurface
            If Not hasExportBoundary Then Return MASImageViewerReadinessStatus.MissingExportBoundary
            If Not hasDedicatedImageSurface OrElse Not hasNoParallelImageServicePath OrElse Not hasNoRunnerOrBackgroundJobPath Then Return MASImageViewerReadinessStatus.HasParallelImageServicePath
            If Not hasMASOwnedSurfaceMaterials Then Return MASImageViewerReadinessStatus.HasSelfOwnedSurfaceMaterial
            If Not hasMouseFocusRingSuppressed Then Return MASImageViewerReadinessStatus.HasBroadMouseFocusRing
            If Not hasPremiumDashboardComposition Then Return MASImageViewerReadinessStatus.MissingTransformSurface
            If Not hasMediaLayoutArchitecture Then Return MASImageViewerReadinessStatus.MissingMediaLayoutArchitecture
            If Not hasImageViewerSurfaceContract Then Return MASImageViewerReadinessStatus.MissingImageViewerSurfaceContract
            Return MASImageViewerReadinessStatus.Ready
        End Function
    End Class

End Namespace
