Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Windows.Forms
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Official Nexamas UI visual data-form surface for business forms, settings panels,
    ''' profile screens, filter summaries, and admin editors. It displays application-owned
    ''' field definitions with premium Nexamas UI layout/material/typography, while binding,
    ''' validation rules, persistence, reflection, editor creation, and submit policy stay owned
    ''' by existing Nexamas UI systems or by the host application.
    ''' </summary>
    Partial Public NotInheritable Class MASDataForm
        Inherits MASControlBase
        Implements IMASLayoutParticipant
        Implements IMASIntrinsicSizeContract

#Region "Fields"

        Private Shared ReadOnly _contract As MASResolvedComponentContract =
            MASArchitectureRuntime.ResolveContractOrThrow(GetType(MASDataForm))

        Private ReadOnly _fields As New List(Of FieldEntry)()
        Private _title As String = DataFormTokens.DefaultTitle
        Private _description As String = DataFormTokens.DefaultDescription
        Private _compact As Boolean
        Private _focusedFieldIndex As Integer = -1
        Private _lastFieldRects() As SKRect = Array.Empty(Of SKRect)()
        Private _disposedLocal As Boolean

#End Region

#Region "Constructor / Factory"

        Public Sub New()
            MyBase.New()
        End Sub

        Public Shared Function Create(Optional configure As Action(Of MASFormBuilder) = Nothing) As MASDataForm
            Dim control As New MASDataForm()
            If configure IsNot Nothing Then
                Dim builder As New MASFormBuilder()
                configure.Invoke(builder)
                control.SetFields(builder)
            End If
            Return control
        End Function

#End Region

#Region "Public API"

        Public Event FieldsChanged As EventHandler

        Public Property Title As String
            Get
                Return _title
            End Get
            Set(value As String)
                Dim normalized As String = MASFormBuilder.NormalizeText(value, DataFormTokens.DefaultTitle)
                If String.Equals(_title, normalized, StringComparison.Ordinal) Then Return
                _title = normalized
                RequestSizeLayoutRefreshForSizeAffectingChange("MASDataForm.Title")
                InvalidateVisual()
            End Set
        End Property

        Public Property Description As String
            Get
                Return _description
            End Get
            Set(value As String)
                Dim normalized As String = MASFormBuilder.NormalizeText(value, String.Empty)
                If String.Equals(_description, normalized, StringComparison.Ordinal) Then Return
                _description = normalized
                RequestSizeLayoutRefreshForSizeAffectingChange("MASDataForm.Description")
                InvalidateVisual()
            End Set
        End Property

        Public Property Compact As Boolean
            Get
                Return _compact
            End Get
            Set(value As Boolean)
                If _compact = value Then Return
                _compact = value
                RequestSizeLayoutRefreshForSizeAffectingChange("MASDataForm.Compact")
                InvalidateVisual()
            End Set
        End Property

        Public ReadOnly Property FieldCount As Integer
            Get
                Return _fields.Count
            End Get
        End Property

        Public Function SetFields(builder As MASFormBuilder) As MASDataForm
            _fields.Clear()

            If builder IsNot Nothing Then
                For Each draft As MASFormBuilder.FieldDraft In builder.Snapshot()
                    If _fields.Count >= DataFormTokens.MaxFields Then Exit For
                    _fields.Add(New FieldEntry(draft.Label, draft.ValueText, draft.Kind, draft.State, draft.HelperText, draft.Required))
                Next
            End If

            NormalizeFocusedFieldAfterCollectionChange()
            RequestSizeLayoutRefreshForSizeAffectingChange("MASDataForm.SetFields")
            RaiseFieldsChangedSafe()
            InvalidateVisual()
            Return Me
        End Function

        Public Function AddField(label As String,
                                 valueText As String,
                                 Optional kind As MASDataFormFieldKind = MASDataFormFieldKind.Text,
                                 Optional state As MASDataFormFieldState = MASDataFormFieldState.Normal,
                                 Optional helperText As String = "",
                                 Optional required As Boolean = False) As MASDataForm
            If _fields.Count >= DataFormTokens.MaxFields Then Return Me
            Dim effectiveState As MASDataFormFieldState = If(required AndAlso state = MASDataFormFieldState.Normal, MASDataFormFieldState.Required, state)
            _fields.Add(New FieldEntry(label, valueText, kind, effectiveState, helperText, required))
            NormalizeFocusedFieldAfterCollectionChange()
            RequestSizeLayoutRefreshForSizeAffectingChange("MASDataForm.AddField")
            RaiseFieldsChangedSafe()
            InvalidateVisual()
            Return Me
        End Function

        Public Function ClearFields() As MASDataForm
            If _fields.Count = 0 Then Return Me
            _fields.Clear()
            NormalizeFocusedFieldAfterCollectionChange()
            RequestSizeLayoutRefreshForSizeAffectingChange("MASDataForm.ClearFields")
            RaiseFieldsChangedSafe()
            InvalidateVisual()
            Return Me
        End Function

        Public Function GetFieldLabel(index As Integer) As String
            If index < 0 OrElse index >= _fields.Count Then Return String.Empty
            Return _fields(index).Label
        End Function

        Public Function GetFieldValue(index As Integer) As String
            If index < 0 OrElse index >= _fields.Count Then Return String.Empty
            Return _fields(index).ValueText
        End Function

        Public Function WithTitle(title As String) As MASDataForm
            Me.Title = title
            Return Me
        End Function

        Public Function WithDescription(description As String) As MASDataForm
            Me.Description = description
            Return Me
        End Function

        Public Function WithCompact(Optional compact As Boolean = True) As MASDataForm
            Me.Compact = compact
            Return Me
        End Function

        Public Shadows Function WithSize(sizeIntent As MASSize) As MASDataForm
            MyBase.SetSize(sizeIntent)
            Return Me
        End Function

#End Region

#Region "Dispose"

        Protected Overrides Sub Dispose(disposing As Boolean)
            If _disposedLocal Then Return
            _disposedLocal = True
            MyBase.Dispose(disposing)
        End Sub

#End Region

    End Class

End Namespace
