Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Official Nexamas UI in-surface notification panel. It presents application-owned
    ''' notification summaries using the existing feedback tone language. Toast lifetime,
    ''' push delivery, background queues, unread persistence, and notification services
    ''' remain owned by applications or existing Nexamas UI feedback systems.
    ''' </summary>
    Partial Public NotInheritable Class MASNotificationPanel
        Inherits MASControlBase
        Implements IMASLayoutParticipant
        Implements IMASIntrinsicSizeContract

#Region "Fields"

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

        Private ReadOnly _items As New List(Of NotificationInfo)()
        Private ReadOnly _hits As New List(Of NotificationRowHit)()
        Private ReadOnly _primitives As New MASVisualPrimitivesPainter()

        Private _title As String = NotificationPanelTokens.DefaultPanelTitle
        Private _hoverIndex As Integer = -1
        Private _pressedIndex As Integer = -1
        Private _emptyTitle As String = NotificationPanelTokens.DefaultEmptyTitle
        Private _emptyMessage As String = NotificationPanelTokens.DefaultEmptyMessage
        Private _showTimestamps As Boolean = True
        Private _disposedLocal As Boolean

#End Region

#Region "Events"

        ''' <summary>
        ''' Raised after notification rows are added, removed, cleared, or read state changes.
        ''' </summary>
        Public Event NotificationsChanged As EventHandler

#End Region

#Region "Constructor / Factory"

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

        Public Shared Function Create(Optional title As String = Nothing) As MASNotificationPanel
            Dim panel As New MASNotificationPanel()
            panel._title = MASNotificationPanelContentPolicy.NormalizeTitle(title, NotificationPanelTokens.DefaultPanelTitle)
            Return panel
        End Function

#End Region

#Region "Public API"

        Public Property Title As String
            Get
                Return _title
            End Get
            Set(value As String)
                Dim normalized As String = NormalizeText(value, NotificationPanelTokens.DefaultPanelTitle)
                If String.Equals(_title, normalized, StringComparison.Ordinal) Then Return

                _title = normalized
                RaiseTextChanged()
                RequestSizeLayoutRefreshForSizeAffectingChange("MASNotificationPanel.Title")
                InvalidateVisual()
            End Set
        End Property

        Public Property EmptyTitle As String
            Get
                Return _emptyTitle
            End Get
            Set(value As String)
                Dim normalized As String = NormalizeText(value, NotificationPanelTokens.DefaultEmptyTitle)
                If String.Equals(_emptyTitle, normalized, StringComparison.Ordinal) Then Return

                _emptyTitle = normalized
                RaiseTextChanged()
                InvalidateVisual()
            End Set
        End Property

        Public Property EmptyMessage As String
            Get
                Return _emptyMessage
            End Get
            Set(value As String)
                Dim normalized As String = NormalizeText(value, NotificationPanelTokens.DefaultEmptyMessage)
                If String.Equals(_emptyMessage, normalized, StringComparison.Ordinal) Then Return

                _emptyMessage = normalized
                RaiseTextChanged()
                InvalidateVisual()
            End Set
        End Property

        Public Property ShowTimestamps As Boolean
            Get
                Return _showTimestamps
            End Get
            Set(value As Boolean)
                If _showTimestamps = value Then Return

                _showTimestamps = value
                InvalidateVisual()
            End Set
        End Property

        Public ReadOnly Property NotificationCount As Integer
            Get
                Return _items.Count
            End Get
        End Property

        Public ReadOnly Property UnreadCount As Integer
            Get
                Dim count As Integer = 0
                For Each item As NotificationInfo In _items
                    If item IsNot Nothing AndAlso item.IsUnread Then count += 1
                Next
                Return count
            End Get
        End Property

        Public Function AddNotification(title As String,
                                        message As String,
                                        Optional tone As MASToastTone = MASToastTone.Info,
                                        Optional timestampText As String = Nothing,
                                        Optional actionText As String = Nothing,
                                        Optional isUnread As Boolean = True) As Integer
            Dim item As New NotificationInfo(title, message, tone, timestampText, actionText, isUnread)
            _items.Add(item)
            StartNotificationPanelMutationMotion(MASMotionTokenId.ItemAdd)
            RequestSizeLayoutRefreshForSizeAffectingChange("MASNotificationPanel.AddNotification")
            InvalidateVisual()
            RaiseNotificationsChangedSafe()
            Return _items.Count - 1
        End Function

        Public Function RemoveNotification(index As Integer) As MASNotificationPanel
            ValidateIndex(index)
            _items.RemoveAt(index)
            StartNotificationPanelMutationMotion(MASMotionTokenId.ItemRemove)
            RequestSizeLayoutRefreshForSizeAffectingChange("MASNotificationPanel.RemoveNotification")
            InvalidateVisual()
            RaiseNotificationsChangedSafe()
            Return Me
        End Function

        Public Function ClearNotifications() As MASNotificationPanel
            If _items.Count = 0 Then Return Me

            _items.Clear()
            StartNotificationPanelMutationMotion(MASMotionTokenId.ItemRemove)
            RequestSizeLayoutRefreshForSizeAffectingChange("MASNotificationPanel.ClearNotifications")
            InvalidateVisual()
            RaiseNotificationsChangedSafe()
            Return Me
        End Function

        Public Function MarkAllRead() As MASNotificationPanel
            Dim changed As Boolean = False
            For Each item As NotificationInfo In _items
                If item IsNot Nothing AndAlso item.IsUnread Then
                    item.IsUnread = False
                    changed = True
                End If
            Next

            If changed Then
                InvalidateVisual()
                RaiseNotificationsChangedSafe()
            End If
            Return Me
        End Function

        Public Function MarkRead(index As Integer) As MASNotificationPanel
            Return SetNotificationRead(index, True)
        End Function

        Public Function SetNotificationRead(index As Integer,
                                            read As Boolean) As MASNotificationPanel
            ValidateIndex(index)
            Dim unread As Boolean = Not read
            If _items(index).IsUnread = unread Then Return Me

            _items(index).IsUnread = unread
            InvalidateVisual()
            RaiseNotificationsChangedSafe()
            Return Me
        End Function

        Public Function GetNotificationTitle(index As Integer) As String
            ValidateIndex(index)
            Return _items(index).Title
        End Function

        Public Function GetNotificationMessage(index As Integer) As String
            ValidateIndex(index)
            Return _items(index).Message
        End Function

        Public Function GetNotificationTone(index As Integer) As MASToastTone
            ValidateIndex(index)
            Return _items(index).Tone
        End Function

        Public Function GetNotificationTimestampText(index As Integer) As String
            ValidateIndex(index)
            Return _items(index).TimestampText
        End Function

        Public Function GetNotificationActionText(index As Integer) As String
            ValidateIndex(index)
            Return _items(index).ActionText
        End Function

        Public Function GetNotificationIsUnread(index As Integer) As Boolean
            ValidateIndex(index)
            Return _items(index).IsUnread
        End Function

        Public Function WithTitle(value As String) As MASNotificationPanel
            Title = value
            Return Me
        End Function

        Public Function WithEmptyText(title As String,
                                      message As String) As MASNotificationPanel
            EmptyTitle = title
            EmptyMessage = message
            Return Me
        End Function

        Public Function WithTimestamps(Optional value As Boolean = True) As MASNotificationPanel
            ShowTimestamps = value
            Return Me
        End Function

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

#End Region
    End Class

End Namespace
