Option Strict On
Option Explicit On

Imports System

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Official internal route for applying surface materials by generic slot/profile. Complex
    ''' elements use this route to say "Header uses CrystalIce" or "apply PremiumGlass profile"
    ''' without creating element-owned material names or drawing recipes.
    ''' </summary>
    Friend NotInheritable Class MASSurfaceMaterialSlotResolver

        Private Sub New()
        End Sub

        Friend Shared Function ResolveSlot(consumerKind As MASSurfaceTreatmentConsumerKind,
                                           slot As MASSurfaceSlot,
                                           Optional materialKey As String = Nothing,
                                           Optional profileId As String = Nothing,
                                           Optional fallbackRole As MASSurfaceRole = MASSurfaceRole.Unknown,
                                           Optional frameStrength As MASSurfaceFrameStrength = MASSurfaceFrameStrength.Level3) As MASSurfaceMaterialSlotRoute
            Dim safeSlot As MASSurfaceSlot = MASSurfaceSlotCatalog.Normalize(slot)
            If safeSlot = MASSurfaceSlot.Unknown Then safeSlot = MASSurfaceSlot.Root

            Dim profileFound As Boolean = False
            Dim profile As MASSurfaceMaterialSlotProfile = Nothing
            Dim hasExplicitMaterialOverride As Boolean = MASSurfaceTreatmentMaterialKeyNormalizer.IsExplicitMaterial(materialKey)
            Dim explicitMaterial As Boolean = hasExplicitMaterialOverride AndAlso
                                             Not MASSurfaceMaterialRuntimeSwitch.IsSwitchableDefaultMaterialKey(materialKey)

            Dim requestedProfileId As String = MASSurfaceMaterialRuntimeSwitch.ResolveProfileForImplicit(
                requestedProfileId:=NormalizeProfileId(profileId),
                requestedMaterialKey:=materialKey,
                hasExplicitMaterialOverride:=explicitMaterial)

            If Not String.Equals(requestedProfileId, MASSurfaceMaterialProfileIds.PlatformDefault, StringComparison.OrdinalIgnoreCase) Then
                profileFound = MASSurfaceMaterialSlotProfileRegistry.TryResolve(requestedProfileId, profile)
            End If
            If profile Is Nothing Then
                profile = MASSurfaceMaterialSlotProfileRegistry.Resolve(requestedProfileId)
            End If

            Dim assignment As MASSurfaceMaterialSlotAssignment = Nothing
            Dim usedSlotFallback As Boolean = False
            Dim activeMaterialKey As String = String.Empty
            Dim activeFrameKey As String = String.Empty
            Dim usedRuntimeMaterialSwitch As Boolean =
                MASSurfaceMaterialRuntimeSwitch.TryResolveActiveMaterialForImplicit(
                    requestedMaterialKey:=materialKey,
                    hasExplicitMaterialOverride:=explicitMaterial,
                    resolvedMaterialKey:=activeMaterialKey,
                    resolvedFrameKey:=activeFrameKey)

            If Not explicitMaterial AndAlso Not usedRuntimeMaterialSwitch Then
                Dim directAssignment As MASSurfaceMaterialSlotAssignment = Nothing
                If profile IsNot Nothing AndAlso profile.TryGetAssignment(safeSlot, directAssignment) Then
                    assignment = directAssignment
                    usedSlotFallback = directAssignment.Slot <> safeSlot
                End If
            End If

            Dim candidateMaterialKey As String = If(explicitMaterial,
                                                    MASSurfaceTreatmentMaterialKeyNormalizer.NormalizeForStorage(materialKey),
                                                    If(usedRuntimeMaterialSwitch,
                                                       activeMaterialKey,
                                                       If(assignment Is Nothing, MASSurfaceMaterialIds.PlatformDefault, assignment.MaterialKey)))
            Dim candidateFrameKey As String = If(explicitMaterial,
                                                 String.Empty,
                                                 If(usedRuntimeMaterialSwitch,
                                                    activeFrameKey,
                                                    If(assignment Is Nothing, String.Empty, assignment.FrameKey)))
            Dim candidateFrameStrength As MASSurfaceFrameStrength = If(assignment Is Nothing OrElse explicitMaterial OrElse usedRuntimeMaterialSwitch,
                                                                       frameStrength,
                                                                       assignment.FrameStrength)
            Dim surfaceStrengthLevel As Integer = If(assignment Is Nothing OrElse explicitMaterial OrElse usedRuntimeMaterialSwitch,
                                                     4,
                                                     assignment.SurfaceStrengthLevel)
            Dim resolvedRole As MASSurfaceRole = MASSurfaceSlotCatalog.ResolveRole(safeSlot, fallbackRole)

            Dim resolution As MASSurfaceTreatmentResolution
            If candidateFrameKey.Length > 0 Then
                resolution = MASSurfaceTreatmentResolver.ResolveMaterialAndFrameOverride(
                    consumerKind:=consumerKind,
                    materialKey:=candidateMaterialKey,
                    frameKey:=candidateFrameKey,
                    frameStrength:=candidateFrameStrength)
            Else
                resolution = MASSurfaceTreatmentResolver.ResolveMaterialOverride(
                    consumerKind:=consumerKind,
                    materialKey:=candidateMaterialKey,
                    frameStrength:=candidateFrameStrength)
            End If

            Dim resolvedMaterialKey As String = If(resolution Is Nothing, candidateMaterialKey, resolution.ResolvedMaterialKey)
            Dim resolvedFrameKey As String = If(resolution Is Nothing, If(candidateFrameKey.Length = 0, MASSurfaceFrameIds.PlatformDefault, candidateFrameKey), resolution.ResolvedFrameKey)

            Return New MASSurfaceMaterialSlotRoute(
                profileId:=If(profile Is Nothing, MASSurfaceMaterialProfileIds.PlatformDefault, profile.Id),
                slot:=safeSlot,
                role:=resolvedRole,
                materialKey:=resolvedMaterialKey,
                frameKey:=resolvedFrameKey,
                frameStrength:=candidateFrameStrength,
                surfaceStrengthLevel:=surfaceStrengthLevel,
                treatmentResolution:=resolution,
                usedProfileFallback:=Not profileFound AndAlso Not String.Equals(requestedProfileId, MASSurfaceMaterialProfileIds.PlatformDefault, StringComparison.OrdinalIgnoreCase),
                usedSlotFallback:=usedSlotFallback)
        End Function

        Friend Shared Function ResolveProfileSlot(consumerKind As MASSurfaceTreatmentConsumerKind,
                                                  profileId As String,
                                                  slot As MASSurfaceSlot,
                                                  Optional fallbackRole As MASSurfaceRole = MASSurfaceRole.Unknown) As MASSurfaceMaterialSlotRoute
            Return ResolveSlot(
                consumerKind:=consumerKind,
                slot:=slot,
                materialKey:=MASSurfaceMaterialIds.Auto,
                profileId:=profileId,
                fallbackRole:=fallbackRole,
                frameStrength:=MASSurfaceFrameStrength.Level3)
        End Function

        Friend Shared Function ResolveMaterialKey(consumerKind As MASSurfaceTreatmentConsumerKind,
                                                   materialKey As String,
                                                   Optional slot As MASSurfaceSlot = MASSurfaceSlot.Root,
                                                   Optional fallbackRole As MASSurfaceRole = MASSurfaceRole.Unknown,
                                                   Optional frameStrength As MASSurfaceFrameStrength = MASSurfaceFrameStrength.Level3) As MASSurfaceMaterialSlotRoute
            Return ResolveSlot(
                consumerKind:=consumerKind,
                slot:=slot,
                materialKey:=materialKey,
                profileId:=MASSurfaceMaterialProfileIds.PlatformDefault,
                fallbackRole:=fallbackRole,
                frameStrength:=frameStrength)
        End Function

        Private Shared Function NormalizeProfileId(value As String) As String
            Dim result As String = If(value, String.Empty).Trim()
            If result.Length = 0 OrElse String.Equals(result, MASSurfaceMaterialProfileIds.Auto, StringComparison.OrdinalIgnoreCase) Then
                Return MASSurfaceMaterialProfileIds.PlatformDefault
            End If

            Return MASSurfaceMaterialSlotProfileRegistry.Canonicalize(result)
        End Function

    End Class

End Namespace
