Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

Namespace Nexamas.UI.SearchBoxSystem

    ''' <summary>
    ''' Friend-owned advanced SearchBox state for suggestions, MRU recent searches, and DataView-compatible filters.
    ''' The state does not render UI, does not own DataGrid projection, and does not create binding sessions.
    ''' </summary>
    Friend NotInheritable Class MASSearchBoxAdvancedState

        Private ReadOnly _suggestions As New List(Of String)()
        Private ReadOnly _recentSearches As New List(Of String)()
        Private ReadOnly _filters As New List(Of MASSearchBoxAdvancedFilterToken)()
        Private _maxRecentSearches As Integer = 8

        Friend Property MaxRecentSearches As Integer
            Get
                Return _maxRecentSearches
            End Get
            Set(value As Integer)
                _maxRecentSearches = Math.Max(0, Math.Min(50, value))
                TrimRecentSearches()
            End Set
        End Property

        Friend ReadOnly Property SuggestionCount As Integer
            Get
                Return _suggestions.Count
            End Get
        End Property

        Friend ReadOnly Property RecentSearchCount As Integer
            Get
                Return _recentSearches.Count
            End Get
        End Property

        Friend ReadOnly Property FilterTokenCount As Integer
            Get
                Return _filters.Count
            End Get
        End Property

        Friend ReadOnly Property HasSuggestionRoute As Boolean
            Get
                Return True
            End Get
        End Property

        Friend ReadOnly Property HasRecentSearchRoute As Boolean
            Get
                Return True
            End Get
        End Property

        Friend ReadOnly Property HasFilterRoute As Boolean
            Get
                Return True
            End Get
        End Property

        Friend Function SetSuggestions(values As IEnumerable(Of String)) As Boolean
            _suggestions.Clear()
            If values IsNot Nothing Then
                For Each value As String In values
                    AddUnique(_suggestions, value)
                Next
            End If
            Return True
        End Function

        Friend Function AddSuggestion(value As String) As Boolean
            Return AddUnique(_suggestions, value)
        End Function

        Friend Function ClearSuggestions() As Boolean
            If _suggestions.Count = 0 Then Return False
            _suggestions.Clear()
            Return True
        End Function

        Friend Function AddRecentSearch(value As String) As Boolean
            Dim normalized As String = Normalize(value)
            If normalized.Length = 0 OrElse _maxRecentSearches <= 0 Then Return False

            RemoveExisting(_recentSearches, normalized)
            _recentSearches.Insert(0, normalized)
            TrimRecentSearches()
            Return True
        End Function

        Friend Function ClearRecentSearches() As Boolean
            If _recentSearches.Count = 0 Then Return False
            _recentSearches.Clear()
            Return True
        End Function

        Friend Function AddColumnFilter(columnKey As String, valueText As String) As Boolean
            Dim token As MASSearchBoxAdvancedFilterToken = MASSearchBoxAdvancedFilterToken.CreateColumnContains(columnKey, valueText)
            If Not token.IsValid Then Return False
            _filters.Add(token)
            Return True
        End Function

        Friend Function AddFilterExpression(expressionText As String) As Boolean
            Dim token As MASSearchBoxAdvancedFilterToken = MASSearchBoxAdvancedFilterToken.CreateExpression(expressionText)
            If Not token.IsValid Then Return False
            _filters.Add(token)
            Return True
        End Function

        Friend Function ClearFilterTokens() As Boolean
            If _filters.Count = 0 Then Return False
            _filters.Clear()
            Return True
        End Function

        Friend Function BuildEffectiveSearchText(baseText As String) As String
            Dim parts As New List(Of String)()
            Dim normalizedBase As String = Normalize(baseText)
            If normalizedBase.Length > 0 Then parts.Add(normalizedBase)

            For Each token As MASSearchBoxAdvancedFilterToken In _filters
                If token IsNot Nothing AndAlso token.IsValid Then parts.Add(token.ExpressionText)
            Next

            If parts.Count = 0 Then Return String.Empty
            Return String.Join(" ", parts.ToArray()).Trim()
        End Function

        Friend Function BuildSuggestionPopupItems(queryText As String, maxItems As Integer) As ReadOnlyCollection(Of String)
            Dim result As New List(Of String)()
            Dim query As String = Normalize(queryText)
            Dim limit As Integer = Math.Max(1, Math.Min(20, maxItems))

            AppendMatches(result, _suggestions, query, limit)
            AppendMatches(result, _recentSearches, query, limit)

            Return New ReadOnlyCollection(Of String)(result)
        End Function

        Friend Function CreateReadinessManifest(hasDataGridBindingRoute As Boolean,
                                                hasViewModelBindingTargetRoute As Boolean,
                                                hasNoParallelSearchPath As Boolean) As MASSearchBoxAdvancedReadinessManifest

            Return MASSearchBoxAdvancedReadinessManifest.Create(
                hasSuggestionRoute:=HasSuggestionRoute,
                hasRecentSearchRoute:=HasRecentSearchRoute,
                hasFilterRoute:=HasFilterRoute,
                hasDataGridBindingRoute:=hasDataGridBindingRoute,
                hasViewModelBindingTargetRoute:=hasViewModelBindingTargetRoute,
                hasNoParallelSearchPath:=hasNoParallelSearchPath)
        End Function

        Private Sub AppendMatches(result As List(Of String), source As List(Of String), query As String, limit As Integer)
            If result Is Nothing OrElse source Is Nothing Then Return

            For Each value As String In source
                If result.Count >= limit Then Exit For
                Dim normalized As String = Normalize(value)
                If normalized.Length = 0 Then Continue For
                If query.Length > 0 AndAlso normalized.IndexOf(query, StringComparison.OrdinalIgnoreCase) < 0 Then Continue For
                If ContainsValue(result, normalized) Then Continue For
                result.Add(normalized)
            Next
        End Sub

        Private Shared Function AddUnique(target As List(Of String), value As String) As Boolean
            If target Is Nothing Then Return False
            Dim normalized As String = Normalize(value)
            If normalized.Length = 0 Then Return False
            If ContainsValue(target, normalized) Then Return False
            target.Add(normalized)
            Return True
        End Function

        Private Shared Sub RemoveExisting(target As List(Of String), value As String)
            If target Is Nothing Then Return
            Dim normalized As String = Normalize(value)
            For index As Integer = target.Count - 1 To 0 Step -1
                If String.Equals(target(index), normalized, StringComparison.OrdinalIgnoreCase) Then
                    target.RemoveAt(index)
                End If
            Next
        End Sub

        Private Shared Function ContainsValue(target As List(Of String), value As String) As Boolean
            If target Is Nothing Then Return False
            Dim normalized As String = Normalize(value)
            For Each item As String In target
                If String.Equals(item, normalized, StringComparison.OrdinalIgnoreCase) Then Return True
            Next
            Return False
        End Function

        Private Sub TrimRecentSearches()
            While _recentSearches.Count > _maxRecentSearches
                _recentSearches.RemoveAt(_recentSearches.Count - 1)
            End While
        End Sub

        Friend Shared Function Normalize(value As String) As String
            If value Is Nothing Then Return String.Empty
            Return value.Trim()
        End Function

    End Class

End Namespace
