using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Library
{
    /// 
    /// Class LuceneSearchEngine
    /// http://www.codeproject.com/Articles/320219/Lucene-Net-ultra-fast-search-for-MVC-or-WebForms
    /// 
    public class SearchEngine : ISearchEngine
    {
        private readonly ILibraryManager _libraryManager;
        private readonly IUserManager _userManager;
        private readonly ILogger _logger;
        public SearchEngine(ILogManager logManager, ILibraryManager libraryManager, IUserManager userManager)
        {
            _libraryManager = libraryManager;
            _userManager = userManager;
            _logger = logManager.GetLogger("Lucene");
        }
        public async Task> GetSearchHints(SearchQuery query)
        {
            IEnumerable inputItems;
            if (string.IsNullOrWhiteSpace(query.UserId))
            {
                inputItems = _libraryManager.RootFolder.RecursiveChildren;
            }
            else
            {
                var user = _userManager.GetUserById(query.UserId);
                inputItems = user.RootFolder.GetRecursiveChildren(user, true);
            }
            inputItems = inputItems.Where(i => !(i is ICollectionFolder));
            inputItems = _libraryManager.ReplaceVideosWithPrimaryVersions(inputItems);
            var results = await GetSearchHints(inputItems, query).ConfigureAwait(false);
            // Include item types
            if (query.IncludeItemTypes.Length > 0)
            {
                results = results.Where(f => query.IncludeItemTypes.Contains(f.Item.GetType().Name, StringComparer.OrdinalIgnoreCase));
            }
            var searchResultArray = results.ToArray();
            results = searchResultArray;
            var count = searchResultArray.Length;
            if (query.StartIndex.HasValue)
            {
                results = results.Skip(query.StartIndex.Value);
            }
            if (query.Limit.HasValue)
            {
                results = results.Take(query.Limit.Value);
            }
            return new QueryResult
            {
                TotalRecordCount = count,
                Items = results.ToArray()
            };
        }
        /// 
        /// Gets the search hints.
        /// 
        /// The input items.
        /// The query.
        /// IEnumerable{SearchHintResult}.
        /// searchTerm
        private Task> GetSearchHints(IEnumerable inputItems, SearchQuery query)
        {
            var searchTerm = query.SearchTerm;
            if (string.IsNullOrWhiteSpace(searchTerm))
            {
                throw new ArgumentNullException("searchTerm");
            }
            var terms = GetWords(searchTerm);
            var hints = new List>();
            var items = inputItems.Where(i => !(i is MusicArtist)).ToList();
            if (query.IncludeMedia)
            {
                // Add search hints based on item name
                hints.AddRange(items.Where(i => !string.IsNullOrWhiteSpace(i.Name)).Select(item =>
                {
                    var index = GetIndex(item.Name, searchTerm, terms);
                    return new Tuple(item, index.Item1, index.Item2);
                }));
            }
            if (query.IncludeArtists)
            {
                // Find artists
                var artists = items.OfType