using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
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 LuceneSearchEngine : ILibrarySearchEngine, IDisposable
    {
        private readonly ILibraryManager _libraryManager;
        private readonly ILogger _logger;
        public LuceneSearchEngine(IServerApplicationPaths serverPaths, ILogManager logManager, ILibraryManager libraryManager)
        {
            _libraryManager = libraryManager;
            _logger = logManager.GetLogger("Lucene");
            //string luceneDbPath = serverPaths.DataPath + "\\SearchIndexDB";
            //if (!System.IO.Directory.Exists(luceneDbPath))
            //    System.IO.Directory.CreateDirectory(luceneDbPath);
            //else if(File.Exists(luceneDbPath + "\\write.lock"))
            //        File.Delete(luceneDbPath + "\\write.lock");
            //LuceneSearch.Init(luceneDbPath, _logger);
            //BaseItem.LibraryManager.LibraryChanged += LibraryChanged;
        }
        //public void LibraryChanged(object source, ChildrenChangedEventArgs changeInformation)
        //{
        //    Task.Run(() =>
        //    {
        //        if (changeInformation.ItemsAdded.Count + changeInformation.ItemsUpdated.Count > 0)
        //        {
        //            LuceneSearch.AddUpdateLuceneIndex(changeInformation.ItemsAdded.Concat(changeInformation.ItemsUpdated));
        //        }
        //        if (changeInformation.ItemsRemoved.Count > 0)
        //        {
        //            LuceneSearch.RemoveFromLuceneIndex(changeInformation.ItemsRemoved);
        //        }
        //    });
        //}
        public void AddItemsToIndex(IEnumerable items)
        {
            LuceneSearch.AddUpdateLuceneIndex(items);
        }
        /// 
        /// Searches items and returns them in order of relevance.
        /// 
        /// The items.
        /// The search term.
        /// IEnumerable{BaseItem}.
        /// searchTerm
        public IEnumerable Search(IEnumerable items, string searchTerm)
        {
            if (string.IsNullOrEmpty(searchTerm))
            {
                throw new ArgumentNullException("searchTerm");
            }
            var hits = LuceneSearch.Search(searchTerm, items.Count());
            //return hits;
            return hits.Where(searchHit => items.Any(p => p.Id == searchHit.Id));
        }
        public void Dispose()
        {
            //BaseItem.LibraryManager.LibraryChanged -= LibraryChanged;
            //LuceneSearch.CloseAll();
        }
        /// 
        /// Gets the search hints.
        /// 
        /// The input items.
        /// The search term.
        /// IEnumerable{SearchHintResult}.
        /// searchTerm
        public async Task> GetSearchHints(IEnumerable inputItems, string searchTerm)
        {
            if (string.IsNullOrEmpty(searchTerm))
            {
                throw new ArgumentNullException("searchTerm");
            }
            var terms = GetWords(searchTerm);
            var hints = new List>();
            var items = inputItems.Where(i => !(i is MusicArtist)).ToList();
            // Add search hints based on item name
            hints.AddRange(items.Where(i => !string.IsNullOrEmpty(i.Name)).Select(item =>
            {
                var index = GetIndex(item.Name, searchTerm, terms);
                return new Tuple(item, index.Item1, index.Item2);
            }));
            // Find artists
            var artists = items.OfType