Option Strict On
Option Explicit On

Imports System.Collections.Generic
Imports Nexamas.UI.Rendering
Imports SkiaSharp

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Internal pointer-state tracker for toast hover/press/hit-test behavior.
    ''' It consumes renderer-owned layout information and does not expose interaction internals to SDK consumers.
    ''' </summary>
    Friend NotInheritable Class MASToastInteractionTracker

        Private _hoveredHit As MASToastHitInfo = MASToastHitInfo.Empty
        Private _pressedHit As MASToastHitInfo = MASToastHitInfo.Empty

        Private _lastLayouts As New Dictionary(Of Integer, MASToastLayoutInfo)()
        Private _lastLayoutOrder As New List(Of MASToastLayoutInfo)()

        Friend ReadOnly Property HoveredHit As MASToastHitInfo
            Get
                Return _hoveredHit
            End Get
        End Property

        Friend ReadOnly Property PressedHit As MASToastHitInfo
            Get
                Return _pressedHit
            End Get
        End Property

        Friend Sub UpdateLayouts(items As List(Of MASToastItem),
                                 arranged As Dictionary(Of Integer, MASToastLayoutInfo))
            _lastLayouts = If(arranged, New Dictionary(Of Integer, MASToastLayoutInfo)())
            _lastLayoutOrder.Clear()

            If items Is Nothing OrElse arranged Is Nothing Then Return

            For i As Integer = items.Count - 1 To 0 Step -1
                Dim item As MASToastItem = items(i)
                If item Is Nothing Then Continue For

                Dim li As New MASToastLayoutInfo()
                If arranged.TryGetValue(item.Id, li) Then
                    _lastLayoutOrder.Add(li)
                End If
            Next
        End Sub

        Friend Function HitTestToast(ptPx As SKPoint) As MASToastHitInfo
            If _lastLayoutOrder Is Nothing OrElse _lastLayoutOrder.Count = 0 Then
                Return MASToastHitInfo.Empty
            End If

            For i As Integer = 0 To _lastLayoutOrder.Count - 1
                Dim li As MASToastLayoutInfo = _lastLayoutOrder(i)

                If Not li.PanelRectPx.Contains(ptPx.X, ptPx.Y) Then
                    Continue For
                End If

                If li.CloseRectPx.Width > 1.0F AndAlso li.CloseRectPx.Contains(ptPx.X, ptPx.Y) Then
                    Return New MASToastHitInfo With {
                        .ToastId = li.ToastId,
                        .Part = MASToastHitPart.CloseButton
                    }
                End If

                If li.UndoRectPx.Width > 1.0F AndAlso li.UndoRectPx.Contains(ptPx.X, ptPx.Y) Then
                    Return New MASToastHitInfo With {
                        .ToastId = li.ToastId,
                        .Part = MASToastHitPart.UndoButton
                    }
                End If

                If li.ActionRectPx.Width > 1.0F AndAlso li.ActionRectPx.Contains(ptPx.X, ptPx.Y) Then
                    Return New MASToastHitInfo With {
                        .ToastId = li.ToastId,
                        .Part = MASToastHitPart.ActionButton
                    }
                End If

                Return New MASToastHitInfo With {
                    .ToastId = li.ToastId,
                    .Part = MASToastHitPart.Body
                }
            Next

            Return MASToastHitInfo.Empty
        End Function

        Friend Function HitTest(ptPx As SKPoint) As Boolean
            Return Not HitTestToast(ptPx).IsEmpty
        End Function

        Friend Function UpdateHover(items As List(Of MASToastItem), ptPx As SKPoint) As Boolean
            SyncAgainstItems(items)

            Dim hit As MASToastHitInfo = HitTestToast(ptPx)

            If _hoveredHit.ToastId = hit.ToastId AndAlso _hoveredHit.Part = hit.Part Then
                Return False
            End If

            _hoveredHit = hit
            ApplyInteractionState(items)
            Return True
        End Function

        Friend Function BeginPress(items As List(Of MASToastItem), ptPx As SKPoint) As Boolean
            SyncAgainstItems(items)

            Dim hit As MASToastHitInfo = HitTestToast(ptPx)
            If hit.IsEmpty Then Return False

            _pressedHit = hit
            ApplyInteractionState(items)
            Return True
        End Function

        Friend Function EndPress(items As List(Of MASToastItem),
                                 ptPx As SKPoint,
                                 ByRef pressed As MASToastHitInfo,
                                 ByRef released As MASToastHitInfo) As Boolean
            SyncAgainstItems(items)

            pressed = _pressedHit
            _pressedHit = MASToastHitInfo.Empty

            If pressed.IsEmpty Then
                released = MASToastHitInfo.Empty
                ApplyInteractionState(items)
                Return False
            End If

            released = HitTestToast(ptPx)
            ApplyInteractionState(items)
            Return True
        End Function

        Friend Sub ClearHover(items As List(Of MASToastItem))
            _hoveredHit = MASToastHitInfo.Empty
            ApplyInteractionState(items)
        End Sub

        Friend Sub ClearPressed(items As List(Of MASToastItem))
            _pressedHit = MASToastHitInfo.Empty
            ApplyInteractionState(items)
        End Sub

        Friend Sub Reset(items As List(Of MASToastItem))
            _hoveredHit = MASToastHitInfo.Empty
            _pressedHit = MASToastHitInfo.Empty
            ApplyInteractionState(items)
            _lastLayouts.Clear()
            _lastLayoutOrder.Clear()
        End Sub

        Friend Sub SyncAgainstItems(items As List(Of MASToastItem))
            If items Is Nothing OrElse items.Count = 0 Then
                _hoveredHit = MASToastHitInfo.Empty
                _pressedHit = MASToastHitInfo.Empty
                Return
            End If

            Dim hoverExists As Boolean = False
            Dim pressExists As Boolean = False

            For Each item As MASToastItem In items
                If item Is Nothing Then Continue For

                If item.Id = _hoveredHit.ToastId Then
                    hoverExists = True
                End If

                If item.Id = _pressedHit.ToastId Then
                    pressExists = True
                End If

                If hoverExists AndAlso pressExists Then Exit For
            Next

            If Not hoverExists Then
                _hoveredHit = MASToastHitInfo.Empty
            End If

            If Not pressExists Then
                _pressedHit = MASToastHitInfo.Empty
            End If

            ApplyInteractionState(items)
        End Sub

        Private Sub ApplyInteractionState(items As List(Of MASToastItem))
            If items Is Nothing Then Return

            For Each item As MASToastItem In items
                If item Is Nothing Then Continue For

                item.IsHovered = False
                item.IsActionHovered = False
                item.IsActionPressed = False
                item.IsUndoHovered = False
                item.IsUndoPressed = False
                item.IsCloseHovered = False
                item.IsClosePressed = False

                If _hoveredHit.ToastId = item.Id Then
                    item.IsHovered = True

                    Select Case _hoveredHit.Part
                        Case MASToastHitPart.ActionButton
                            item.IsActionHovered = True

                        Case MASToastHitPart.UndoButton
                            item.IsUndoHovered = True

                        Case MASToastHitPart.CloseButton
                            item.IsCloseHovered = True
                    End Select
                End If

                If _pressedHit.ToastId = item.Id Then
                    Select Case _pressedHit.Part
                        Case MASToastHitPart.ActionButton
                            item.IsActionPressed = True

                        Case MASToastHitPart.UndoButton
                            item.IsUndoPressed = True

                        Case MASToastHitPart.CloseButton
                            item.IsClosePressed = True
                    End Select
                End If
            Next
        End Sub

    End Class

End Namespace