Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic

Namespace Nexamas.UI.Rendering

    Friend NotInheritable Class MASSurfaceMaterialRegistry
        Private Shared ReadOnly _sync As New Object()
        Private Shared ReadOnly _definitions As New Dictionary(Of String, MASSurfaceMaterialDefinition)(StringComparer.OrdinalIgnoreCase)
        Private Shared ReadOnly _aliases As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
        Private Shared _initialized As Boolean = False

        Private Sub New()
        End Sub

        Friend Shared Sub Register(material As IMASSurfaceMaterial)
            If material Is Nothing Then Throw New ArgumentNullException(NameOf(material))
            If String.IsNullOrWhiteSpace(material.Id) Then Throw New ArgumentException("Material Id is required.", NameOf(material))

            RegisterDefinition(New MASSurfaceMaterialDefinition(
                id:=material.Id,
                displayName:=material.Id,
                material:=material,
                category:=MASSurfaceMaterialCategory.Unknown,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.PlatformDefault,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeBound,
                isPublicSelectable:=False,
                preservesMaterialIdentity:=False,
                recommendedRoles:=Nothing,
                notes:="Runtime material registration without catalog metadata."))
        End Sub

        Friend Shared Sub RegisterDefinition(definition As MASSurfaceMaterialDefinition)
            If definition Is Nothing Then Throw New ArgumentNullException(NameOf(definition))

            SyncLock _sync
                EnsureDefaultsNoLock()
                _definitions(definition.Id) = definition
            End SyncLock
        End Sub

        Friend Shared Function Resolve(materialKey As String,
                                       Optional fallback As IMASSurfaceMaterial = Nothing) As IMASSurfaceMaterial
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim definition As MASSurfaceMaterialDefinition = Nothing
                If TryResolveDefinitionNoLock(materialKey, definition) Then Return definition.Material
                If fallback IsNot Nothing Then Return fallback

                Return _definitions(MASSurfaceMaterialIds.PlatformDefault).Material
            End SyncLock
        End Function

        Friend Shared Function TryResolve(materialKey As String,
                                          ByRef material As IMASSurfaceMaterial) As Boolean
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim definition As MASSurfaceMaterialDefinition = Nothing
                If TryResolveDefinitionNoLock(materialKey, definition) Then
                    material = definition.Material
                    Return True
                End If

                material = Nothing
                Return False
            End SyncLock
        End Function

        Friend Shared Function ResolveDefinition(materialKey As String) As MASSurfaceMaterialDefinition
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim definition As MASSurfaceMaterialDefinition = Nothing
                If TryResolveDefinitionNoLock(materialKey, definition) Then Return definition

                Return _definitions(MASSurfaceMaterialIds.PlatformDefault)
            End SyncLock
        End Function

        Friend Shared Function TryResolveDefinition(materialKey As String,
                                                    ByRef definition As MASSurfaceMaterialDefinition) As Boolean
            SyncLock _sync
                EnsureDefaultsNoLock()
                Return TryResolveDefinitionNoLock(materialKey, definition)
            End SyncLock
        End Function

        Friend Shared Function Contains(materialKey As String) As Boolean
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim definition As MASSurfaceMaterialDefinition = Nothing
                Return TryResolveDefinitionNoLock(materialKey, definition)
            End SyncLock
        End Function

        Friend Shared Function RegisteredDefinitions() As MASSurfaceMaterialDefinition()
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim result As New List(Of MASSurfaceMaterialDefinition)()
                For Each definition As MASSurfaceMaterialDefinition In _definitions.Values
                    If definition IsNot Nothing Then result.Add(definition)
                Next

                Return result.ToArray()
            End SyncLock
        End Function

        Friend Shared Function RegisteredPublicDefinitions() As MASSurfaceMaterialDefinition()
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim result As New List(Of MASSurfaceMaterialDefinition)()
                For Each definition As MASSurfaceMaterialDefinition In _definitions.Values
                    If definition IsNot Nothing AndAlso definition.IsPublicSelectable Then result.Add(definition)
                Next

                Return result.ToArray()
            End SyncLock
        End Function

        Friend Shared Function IsCompatibilityAlias(materialKey As String) As Boolean
            SyncLock _sync
                EnsureDefaultsNoLock()

                Dim key As String = NormalizeAliasKey(materialKey)
                If key.Length = 0 Then Return False
                Return _aliases.ContainsKey(key)
            End SyncLock
        End Function

        Friend Shared Function Canonicalize(materialKey As String) As String
            SyncLock _sync
                EnsureDefaultsNoLock()
                Return CanonicalizeNoLock(materialKey)
            End SyncLock
        End Function

        Private Shared Function TryResolveDefinitionNoLock(materialKey As String,
                                                           ByRef definition As MASSurfaceMaterialDefinition) As Boolean
            Dim key As String = MASSurfaceTreatmentMaterialKeyNormalizer.NormalizeForResolution(materialKey)
            key = CanonicalizeNoLock(key)

            If _definitions.TryGetValue(key, definition) Then Return True

            definition = Nothing
            Return False
        End Function

        Private Shared Function CanonicalizeNoLock(materialKey As String) As String
            Dim key As String = NormalizeAliasKey(materialKey)
            If key.Length = 0 Then Return MASSurfaceMaterialIds.PlatformDefault

            Dim canonical As String = Nothing
            If _aliases.TryGetValue(key, canonical) Then Return canonical

            Return key
        End Function

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

        Private Shared Sub EnsureDefaultsNoLock()
            If _initialized Then Return

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.PlatformDefault,
                displayName:="Platform Default",
                material:=New NexamasUIDefaultSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Platform,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.PlatformDefault,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeBound,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=False,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.PanelShell, MASSurfaceRole.Dialog, MASSurfaceRole.Card, MASSurfaceRole.Control},
                notes:="Default Nexamas UI surface material; strongly follows ThemeSystem and preserves current default visuals."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.SoftMist,
                displayName:="Soft Mist",
                material:=New MASSoftMistSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Mist,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.SoftMist,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Card, MASSurfaceRole.PanelShell, MASSurfaceRole.Control},
                notes:="Theme-tinted soft mist material that keeps its mist identity."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.FrostedGlass,
                displayName:="Frosted Glass",
                material:=New MASFrostedGlassSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Glass,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.FrostedGlass,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Popup, MASSurfaceRole.DropDown, MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Card},
                notes:="Theme-harmonized glass material; it does not become a plain theme fill."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.CrystalIce,
                displayName:="Crystal Ice",
                material:=New MASCrystalIceSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Crystal,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.CrystalIce,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Popup, MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Card},
                notes:="Theme-tinted crystal material for surfaces that should harmonize with the active theme."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.CrystalIceNative,
                displayName:="Crystal Ice Native",
                material:=New MASCrystalIceNativeSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Crystal,
                materialVariant:=MASSurfaceMaterialVariant.Native,
                defaultFrameKey:=MASSurfaceFrameIds.CrystalIce,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.IdentityPreserving,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Popup, MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Card},
                notes:="Native CrystalIce variant; preserves its own palette and is suitable as a future theme seed."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.WarmPaper,
                displayName:="Warm Paper",
                material:=New MASWarmPaperSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Paper,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.WarmPaper,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Dialog, MASSurfaceRole.Card, MASSurfaceRole.Control},
                notes:="Theme-tinted warm paper material for readable calm surfaces."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.WarmPaperNative,
                displayName:="Warm Paper Native",
                material:=New MASWarmPaperNativeSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Paper,
                materialVariant:=MASSurfaceMaterialVariant.Native,
                defaultFrameKey:=MASSurfaceFrameIds.WarmPaper,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.IdentityPreserving,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Dialog, MASSurfaceRole.Card, MASSurfaceRole.Control},
                notes:="Native WarmPaper variant; preserves its own warm paper palette and can seed a future theme."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.GraphiteMetal,
                displayName:="Graphite Metal",
                material:=New MASGraphiteMetalSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Metal,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.GraphiteMetal,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.IdentityPreserving,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.ApplicationChrome, MASSurfaceRole.PanelShell, MASSurfaceRole.Card},
                notes:="Graphite metal material; theme use is limited and compatibility-driven."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MediaShell,
                displayName:="Media Shell",
                material:=New MASMediaShellSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Media,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.SoftMist,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Card, MASSurfaceRole.PanelShell, MASSurfaceRole.Control},
                notes:="Theme-tinted media shell material for image, video, and document display surfaces."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MediaChrome,
                displayName:="Media Chrome",
                material:=New MASMediaChromeSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Media,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.SoftMist,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Popup, MASSurfaceRole.Card},
                notes:="Theme-tinted media header and floating command rail for image, video, and document surfaces."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MediaToolbarGlass,
                displayName:="Media Toolbar Glass",
                material:=New MASMediaToolbarGlassSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Media,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.FrostedGlass,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Popup},
                notes:="Semi-transparent media toolbar glass, authored at about 70 percent opacity for pinned and floating command rails."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MediaCommandRail,
                displayName:="Media Command Rail",
                material:=New MASMediaCommandRailSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Media,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.SoftMist,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.ApplicationChrome},
                notes:="Dedicated satin media toolbar rail for pinned viewer command surfaces; distinct from general glass and platform chrome materials."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MediaFooterChrome,
                displayName:="Media Footer Chrome",
                material:=New MASMediaFooterChromeSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Media,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.SoftMist,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Card},
                notes:="Theme-tinted grounded footer rail for media metadata and zoom state."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MediaStage,
                displayName:="Media Stage",
                material:=New MASMediaStageSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Media,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.PlatformDefault,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeTinted,
                isPublicSelectable:=True,
                preservesMaterialIdentity:=True,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.Control, MASSurfaceRole.Card},
                notes:="Theme-tinted neutral media stage material behind bitmap and document render surfaces."))

            AddDefinitionNoLock(New MASSurfaceMaterialDefinition(
                id:=MASSurfaceMaterialIds.MenuBarFlat,
                displayName:="Menu Bar Flat",
                material:=New MASMenuBarFlatSurfaceMaterial(),
                category:=MASSurfaceMaterialCategory.Platform,
                materialVariant:=MASSurfaceMaterialVariant.Adaptive,
                defaultFrameKey:=MASSurfaceFrameIds.PlatformDefault,
                themeInfluenceMode:=MASSurfaceTreatmentThemeInfluenceMode.ThemeBound,
                isPublicSelectable:=False,
                preservesMaterialIdentity:=False,
                recommendedRoles:=New MASSurfaceRole() {MASSurfaceRole.ApplicationChrome, MASSurfaceRole.Control},
                notes:="Theme-owned flat attached shell navigation material for MASMenuBar chrome; not a general-purpose selectable surface."))

            AddAliasNoLock(MASSurfaceMaterialIds.LegacyPlatformDefault, MASSurfaceMaterialIds.PlatformDefault)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacySoftMist, MASSurfaceMaterialIds.SoftMist)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacyFrostedGlass, MASSurfaceMaterialIds.FrostedGlass)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacyCrystalIce, MASSurfaceMaterialIds.CrystalIce)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacyWarmPaper, MASSurfaceMaterialIds.WarmPaper)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacyGraphiteMetal, MASSurfaceMaterialIds.GraphiteMetal)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacyCrystalIceNativeAlias, MASSurfaceMaterialIds.CrystalIceNative)
            AddAliasNoLock(MASSurfaceMaterialIds.LegacyWarmPaperNativeAlias, MASSurfaceMaterialIds.WarmPaperNative)

            _initialized = True
        End Sub

        Private Shared Sub AddDefinitionNoLock(definition As MASSurfaceMaterialDefinition)
            If definition Is Nothing Then Return
            _definitions(definition.Id) = definition
        End Sub

        Private Shared Sub AddAliasNoLock(aliasKey As String,
                                          canonicalKey As String)
            Dim safeAlias As String = NormalizeAliasKey(aliasKey)
            Dim safeCanonical As String = NormalizeAliasKey(canonicalKey)
            If safeAlias.Length = 0 OrElse safeCanonical.Length = 0 Then Return
            If String.Equals(safeAlias, safeCanonical, StringComparison.OrdinalIgnoreCase) Then Return
            _aliases(safeAlias) = safeCanonical
        End Sub
    End Class

End Namespace
