Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Canonical definition for one registered surface material. The registry owns these
    ''' definitions so material identity, drawing, frame pairing, theme influence, and designer
    ''' availability are not split across parallel catalogs.
    ''' </summary>
    Friend NotInheritable Class MASSurfaceMaterialDefinition

        Private ReadOnly _recommendedRoles As MASSurfaceRole()

        Friend Sub New(id As String,
                       displayName As String,
                       material As IMASSurfaceMaterial,
                       category As MASSurfaceMaterialCategory,
                       materialVariant As MASSurfaceMaterialVariant,
                       defaultFrameKey As String,
                       themeInfluenceMode As MASSurfaceTreatmentThemeInfluenceMode,
                       isPublicSelectable As Boolean,
                       preservesMaterialIdentity As Boolean,
                       recommendedRoles As IEnumerable(Of MASSurfaceRole),
                       notes As String)

            If material Is Nothing Then Throw New ArgumentNullException(NameOf(material))

            Dim safeId As String = Normalize(id)
            If safeId.Length = 0 Then Throw New ArgumentException("Material Id is required.", NameOf(id))
            If Not String.Equals(safeId, Normalize(material.Id), StringComparison.OrdinalIgnoreCase) Then
                Throw New ArgumentException("Material definition Id must match the material instance Id.", NameOf(id))
            End If

            Me.Id = safeId
            Me.DisplayName = If(Normalize(displayName).Length = 0, safeId, Normalize(displayName))
            Me.Material = material
            Me.Category = category
            Me.MaterialVariant = If(materialVariant = MASSurfaceMaterialVariant.Unknown, MASSurfaceMaterialVariant.Adaptive, materialVariant)
            Me.DefaultFrameKey = NormalizeWithFallback(defaultFrameKey, MASSurfaceFrameIds.PlatformDefault)
            Me.ThemeInfluenceMode = If(themeInfluenceMode = MASSurfaceTreatmentThemeInfluenceMode.Unknown,
                                       MASSurfaceTreatmentThemeInfluenceMode.ThemeBound,
                                       themeInfluenceMode)
            Me.IsPublicSelectable = isPublicSelectable
            Me.PreservesMaterialIdentity = preservesMaterialIdentity
            Me.Notes = Normalize(notes)
            _recommendedRoles = NormalizeRoles(recommendedRoles)
        End Sub

        Friend ReadOnly Property Id As String
        Friend ReadOnly Property DisplayName As String
        Friend ReadOnly Property Material As IMASSurfaceMaterial
        Friend ReadOnly Property Category As MASSurfaceMaterialCategory
        Friend ReadOnly Property MaterialVariant As MASSurfaceMaterialVariant
        Friend ReadOnly Property DefaultFrameKey As String
        Friend ReadOnly Property ThemeInfluenceMode As MASSurfaceTreatmentThemeInfluenceMode
        Friend ReadOnly Property IsPublicSelectable As Boolean
        Friend ReadOnly Property PreservesMaterialIdentity As Boolean
        Friend ReadOnly Property Notes As String

        Friend ReadOnly Property IsNativeVariant As Boolean
            Get
                Return MaterialVariant = MASSurfaceMaterialVariant.Native
            End Get
        End Property

        Friend ReadOnly Property RecommendedRoles As MASSurfaceRole()
            Get
                Return DirectCast(_recommendedRoles.Clone(), MASSurfaceRole())
            End Get
        End Property

        Friend Function ToTreatmentProfile() As MASSurfaceTreatmentMaterialProfile
            Return New MASSurfaceTreatmentMaterialProfile(
                materialKey:=Id,
                recommendedFrameKey:=DefaultFrameKey,
                themeInfluenceMode:=ThemeInfluenceMode,
                isCompatibilityAlias:=False,
                preservesMaterialIdentity:=PreservesMaterialIdentity,
                notes:=Notes)
        End Function

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

        Private Shared Function NormalizeWithFallback(value As String,
                                                      fallback As String) As String
            Dim result As String = Normalize(value)
            If result.Length = 0 Then Return fallback
            Return result
        End Function

        Private Shared Function NormalizeRoles(roles As IEnumerable(Of MASSurfaceRole)) As MASSurfaceRole()
            If roles Is Nothing Then Return New MASSurfaceRole() {}

            Dim result As New List(Of MASSurfaceRole)()
            For Each role As MASSurfaceRole In roles
                If role = MASSurfaceRole.Unknown Then Continue For
                If Not result.Contains(role) Then result.Add(role)
            Next

            Return result.ToArray()
        End Function

    End Class

End Namespace
