Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Components
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Motion
Imports SkiaSharp

Namespace Nexamas.UI.Controls

    Partial Public NotInheritable Class MASTabControl
        Inherits MASControlBase
        Implements IMASLayoutParticipant
        Implements IMASIntrinsicSizeContract

#Region "Fields"

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

        Private ReadOnly _items As New List(Of MASTabItem)()
        Private ReadOnly _itemsView As IReadOnlyList(Of MASTabItem)
        Private ReadOnly _renderer As MASTabRenderer

        Private _selectedIndex As Integer = -1
        Private _hoverIndex As Integer = -1
        Private _pressedIndex As Integer = -1

        Private _hoverNav As MASTabNavButtonKind = MASTabNavButtonKind.None
        Private _pressedNav As MASTabNavButtonKind = MASTabNavButtonKind.None

        Private _scrollOffsetPx As Single = 0.0F
        Private _targetScrollOffsetPx As Single = 0.0F
        Private _scrollMotionStartPx As Single = 0.0F
        Private _maxScrollOffsetPx As Single = 0.0F
        Private _viewportWidthPx As Single = 0.0F
        Private _pendingEnsureSelectedVisible As Boolean = False
        Private _scrollMotionRunner As MASMotionTimelineRunner
        Private _selectionIndicatorRunner As MASMotionTimelineRunner
        Private _selectionIndicatorFromIndex As Integer = -1
        Private _selectionIndicatorToIndex As Integer = -1
        Private _selectionIndicatorProgress As Single = 1.0F
        Private _hasSelectionIndicatorMotion As Boolean

#End Region


#Region "Events"

        Public Event SelectedIndexChanged As EventHandler
        Public Event SelectedItemChanged As EventHandler

#End Region


#Region "Ctor"

        Public Sub New()
            _contract.AssertConsumable()
            _itemsView = _items.AsReadOnly()

            _renderer = New MASTabRenderer(New Nexamas.UI.Rendering.MASVisualPrimitivesPainter())

             SetLocalLayoutBoundsInternal(New SKRect(0.0F, 0.0F, 320.0F, 40.0F))
        End Sub

#End Region


#Region "Factories"

        Public Shared Function Create() As MASTabControl
            Return New MASTabControl()
        End Function

#End Region


#Region "Public API"

        Friend Sub SetBounds(bounds As SKRect)
            SetBounds(bounds.Left, bounds.Top, bounds.Width, bounds.Height)
        End Sub

        Friend Sub SetBounds(x As Single,
                             y As Single,
                             width As Single,
                             height As Single)

             SetLocalLayoutBoundsInternal(New SKRect(
                x,
                y,
                x + Math.Max(0.0F, width),
                y + Math.Max(0.0F, height)
            ))
        End Sub

        Friend Function WithBounds(bounds As SKRect) As MASTabControl
            SetBounds(bounds)
            Return Me
        End Function

        Friend Function WithBounds(x As Single,
                                   y As Single,
                                   width As Single,
                                   height As Single) As MASTabControl

            SetBounds(x, y, width, height)
            Return Me
        End Function

        Public Function WithTab(text As String,
                                Optional key As String = "",
                                Optional enabled As Boolean = True) As MASTabControl

            AddTab(text, key, enabled)
            Return Me
        End Function

        Public Function WithSelectedIndex(value As Integer) As MASTabControl
            SelectedIndex = value
            Return Me
        End Function


        Public ReadOnly Property Items As IReadOnlyList(Of MASTabItem)
            Get
                Return _itemsView
            End Get
        End Property

        Friend ReadOnly Property HoverIndex As Integer
            Get
                Return _hoverIndex
            End Get
        End Property

        Public ReadOnly Property PressedIndex As Integer
            Get
                Return _pressedIndex
            End Get
        End Property

        Friend ReadOnly Property HoverNavButton As MASTabNavButtonKind
            Get
                Return _hoverNav
            End Get
        End Property

        Friend ReadOnly Property PressedNavButton As MASTabNavButtonKind
            Get
                Return _pressedNav
            End Get
        End Property

        Friend ReadOnly Property ScrollOffsetPx As Single
            Get
                Return _scrollOffsetPx
            End Get
        End Property

        Public Property SelectedIndex As Integer
            Get
                Return _selectedIndex
            End Get
            Set(value As Integer)
                Dim normalized As Integer = NormalizeSelectableIndex(value)
                If _selectedIndex = normalized Then Return

                Dim previous As Integer = _selectedIndex
                _selectedIndex = normalized
                _pendingEnsureSelectedVisible = True
                StartSelectionIndicatorMotion(previous, normalized)

                RaiseEvent SelectedIndexChanged(Me, EventArgs.Empty)
                RaiseEvent SelectedItemChanged(Me, EventArgs.Empty)
                InvalidateVisual()
            End Set
        End Property

        Public ReadOnly Property SelectedItem As MASTabItem
            Get
                If _selectedIndex < 0 OrElse _selectedIndex >= _items.Count Then Return Nothing
                Return _items(_selectedIndex)
            End Get
        End Property

        Public Function AddTab(text As String,
                               Optional key As String = "",
                               Optional enabled As Boolean = True) As MASTabItem

            Dim item As New MASTabItem(text, key, enabled)
            _items.Add(item)

            If _selectedIndex < 0 AndAlso enabled Then
                _selectedIndex = _items.Count - 1
                _pendingEnsureSelectedVisible = True
            End If

            InvalidateVisual()
            Return item
        End Function

        Public Sub ClearTabs()
            _items.Clear()
            _selectedIndex = -1
            _hoverIndex = -1
            _pressedIndex = -1
            _hoverNav = MASTabNavButtonKind.None
            _pressedNav = MASTabNavButtonKind.None
            _scrollOffsetPx = 0.0F
            _targetScrollOffsetPx = 0.0F
            _maxScrollOffsetPx = 0.0F
            _viewportWidthPx = 0.0F
            _pendingEnsureSelectedVisible = False
            StopAnimation()
            StopSelectionIndicatorMotion()
            InvalidateVisual()
        End Sub

#End Region
    End Class

End Namespace
