﻿Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic

Partial Friend NotInheritable Class ShowcaseNavigationCatalog

    Friend Shared Function SearchEntries(query As String,
                                         Optional maximumCount As Integer = 12) As IReadOnlyList(Of ShowcaseNavigationEntry)
        Dim normalizedQuery As String = NormalizeSearchQuery(query)
        Dim result As New List(Of ShowcaseNavigationEntry)()
        If maximumCount <= 0 Then Return result.AsReadOnly()

        If normalizedQuery.Length = 0 Then
            For Each entry As ShowcaseNavigationEntry In _entries
                If entry Is Nothing Then Continue For
                result.Add(entry)
                If result.Count >= maximumCount Then Exit For
            Next
            Return result.AsReadOnly()
        End If

        For Each entry As ShowcaseNavigationEntry In _entries
            If entry Is Nothing Then Continue For
            If EntryMatchesQuery(entry, normalizedQuery) Then
                result.Add(entry)
                If result.Count >= maximumCount Then Exit For
            End If
        Next

        Return result.AsReadOnly()
    End Function

    Friend Shared Function FindFirstSearchResult(query As String) As ShowcaseNavigationEntry
        Dim matches As IReadOnlyList(Of ShowcaseNavigationEntry) = SearchEntries(query, 1)
        If matches.Count = 0 Then Return Nothing
        Return matches(0)
    End Function

    Friend Shared Function BuildSearchIndexText(entry As ShowcaseNavigationEntry) As String
        If entry Is Nothing Then Return String.Empty

        Return entry.Id & " " &
               entry.Title & " " &
               entry.Summary & " " &
               ResolveCategoryTitle(entry.Category) & " " &
               ResolveEntryKindTitle(ResolveEntryKind(entry))
    End Function

    Private Shared Function NormalizeSearchQuery(query As String) As String
        Return If(query, String.Empty).Trim()
    End Function

    Private Shared Function EntryMatchesQuery(entry As ShowcaseNavigationEntry,
                                              normalizedQuery As String) As Boolean
        If entry Is Nothing Then Return False
        If normalizedQuery.Length = 0 Then Return True

        Dim terms As String() = normalizedQuery.Split(New Char() {" "c, ControlChars.Tab}, StringSplitOptions.RemoveEmptyEntries)
        If terms.Length = 0 Then Return True

        Dim haystack As String = BuildSearchIndexText(entry)
        For Each term As String In terms
            If haystack.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0 Then
                Return False
            End If
        Next

        Return True
    End Function
End Class
