Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
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.Motion
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 content-carousel surface. It owns product-readable
    ''' carousel item composition, same-surface previous/next navigation, selection,
    ''' keyboard navigation, RTL-aware layout, and readiness evidence. Galleries, image
    ''' loading, slide decks, onboarding engines, content providers, auto-rotation clocks,
    ''' local/parallel transition schedulers, wrappers, adapters, and native controls remain outside it.
    ''' Official MASMotionSystem timelines are the only allowed motion route.
    ''' </summary>
    Partial Public NotInheritable Class MASContentCarousel
        Inherits MASControlBase
        Implements IMASLayoutParticipant
        Implements IMASIntrinsicSizeContract

#Region "Nested state"

        Private NotInheritable Class CarouselItemState
            Friend Sub New(key As String,
                           title As String,
                           subtitle As String,
                           detail As String)
                Me.Key = key
                Me.Title = title
                Me.Subtitle = subtitle
                Me.Detail = detail
            End Sub

            Friend ReadOnly Property Key As String
            Friend Property Title As String
            Friend Property Subtitle As String
            Friend Property Detail As String
        End Class

        Private Enum CarouselHitKind
            None = 0
            PreviousButton = 1
            NextButton = 2
            Item = 3
            Indicator = 4
        End Enum

        Private NotInheritable Class CarouselHit
            Friend Sub New(kind As CarouselHitKind,
                           index As Integer,
                           rect As SKRect)
                Me.Kind = kind
                Me.Index = index
                Me.Rect = rect
            End Sub

            Friend ReadOnly Property Kind As CarouselHitKind
            Friend ReadOnly Property Index As Integer
            Friend ReadOnly Property Rect As SKRect
        End Class

#End Region

#Region "Fields"

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

        Private ReadOnly _primitives As New MASVisualPrimitivesPainter()
        Private ReadOnly _items As New List(Of CarouselItemState)()
        Private ReadOnly _hits As New List(Of CarouselHit)()
        Private _title As String = ContentCarouselTokens.DefaultTitle
        Private _selectedIndex As Integer = -1
        Private _hoverKind As CarouselHitKind = CarouselHitKind.None
        Private _hoverIndex As Integer = -1
        Private _pressedKind As CarouselHitKind = CarouselHitKind.None
        Private _pressedIndex As Integer = -1
        Private _isLooping As Boolean = True
        Private _selectionMotionRunner As MASMotionTimelineRunner
        Private _motionFromIndex As Integer = -1
        Private _motionToIndex As Integer = -1
        Private _motionProgress As Single = 1.0F
        Private _motionDirection As Integer = 1
        Private _contentRect As SKRect = SKRect.Empty
        Private _stageRect As SKRect = SKRect.Empty
        Private _lastDpi As Single = 1.0F

#End Region

#Region "Constructor / Factory"

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

        Public Shared Function Create(Optional title As String = Nothing) As MASContentCarousel
            Dim control As New MASContentCarousel()
            control._title = MASContentCarouselPolicy.NormalizeTitle(title)
            Return control
        End Function

#End Region

#Region "Public API"

        Public Event ContentCarouselChanged As EventHandler
        Public Event SelectedItemChanged As EventHandler

        Public Property Title As String
            Get
                Return _title
            End Get
            Set(value As String)
                Dim normalized As String = MASContentCarouselPolicy.NormalizeTitle(value)
                If String.Equals(_title, normalized, StringComparison.Ordinal) Then Return
                _title = normalized
                RequestSizeLayoutRefreshForSizeAffectingChange("MASContentCarousel.Title")
                InvalidateVisual()
            End Set
        End Property

        Public Property IsLooping As Boolean
            Get
                Return _isLooping
            End Get
            Set(value As Boolean)
                If _isLooping = value Then Return
                _isLooping = value
                InvalidateVisual()
            End Set
        End Property

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

        Public ReadOnly Property SelectedIndex As Integer
            Get
                Return _selectedIndex
            End Get
        End Property

        Public ReadOnly Property SelectedItemKey As String
            Get
                If _selectedIndex < 0 OrElse _selectedIndex >= _items.Count Then Return String.Empty
                Return _items(_selectedIndex).Key
            End Get
        End Property

        Public ReadOnly Property SummaryText As String
            Get
                Return MASContentCarouselPolicy.BuildSummary(ItemCount, _selectedIndex)
            End Get
        End Property

        Public Function GetItemKeys() As IReadOnlyList(Of String)
            Dim keys As New List(Of String)()
            For Each item As CarouselItemState In _items
                keys.Add(item.Key)
            Next
            Return New ReadOnlyCollection(Of String)(keys)
        End Function

        Public Function AddItem(itemKey As String,
                                title As String,
                                Optional subtitle As String = Nothing,
                                Optional detail As String = Nothing) As MASContentCarousel
            If _items.Count >= ContentCarouselTokens.MaxItems Then Return Me
            Dim normalizedKey As String = MASContentCarouselPolicy.NormalizeKey(itemKey, "item", _items.Count + 1)
            If FindItemIndex(normalizedKey) >= 0 Then Return Me
            _items.Add(New CarouselItemState(normalizedKey,
                                             MASContentCarouselPolicy.NormalizeItemTitle(title),
                                             MASContentCarouselPolicy.NormalizeSubtitle(subtitle),
                                             MASContentCarouselPolicy.NormalizeDetail(detail)))
            If _selectedIndex < 0 Then _selectedIndex = 0
            NormalizeSelection()
            RequestSizeLayoutRefreshForSizeAffectingChange("MASContentCarousel.AddItem")
            InvalidateVisual()
            RaiseContentCarouselChangedSafe()
            Return Me
        End Function

        Public Function ClearItems() As MASContentCarousel
            If _items.Count = 0 Then Return Me
            CancelSelectionMotion()
            _items.Clear()
            _selectedIndex = -1
            ResetPointerState()
            RequestSizeLayoutRefreshForSizeAffectingChange("MASContentCarousel.ClearItems")
            InvalidateVisual()
            RaiseContentCarouselChangedSafe()
            RaiseSelectedItemChangedSafe()
            Return Me
        End Function

        Public Function SelectItem(itemKey As String) As Boolean
            Dim index As Integer = FindItemIndex(itemKey)
            If index < 0 Then Return False
            SetSelectedIndex(index, True)
            Return True
        End Function

        Public Function MovePrevious() As MASContentCarousel
            MoveBy(-1)
            Return Me
        End Function

        Public Function MoveNext() As MASContentCarousel
            MoveBy(1)
            Return Me
        End Function

        Public Function MoveFirst() As MASContentCarousel
            SetSelectedIndex(0, True)
            Return Me
        End Function

        Public Function MoveLast() As MASContentCarousel
            SetSelectedIndex(_items.Count - 1, True)
            Return Me
        End Function

        Public Function WithLooping(value As Boolean) As MASContentCarousel
            IsLooping = value
            Return Me
        End Function

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

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

#End Region



    End Class

End Namespace

