using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Web;
using LuceneNet.Models;

namespace LuceneNet.Filters
{
    /// <summary>
    /// 同步更新数据库和索引文件
    /// </summary>
    public class IndexManager
    {
        public static readonly IndexManager pageIndex = new IndexManager();
        public static readonly string indexPath = HttpContext.Current.Server.MapPath("~/IndexData");
        private IndexManager()
        {
        }
        //请求队列 解决索引目录同时操作的并发问题
        private Queue<PageViewMode> pageQueue = new Queue<PageViewMode>();
        /// <summary>
        /// 新增Pages表信息时 添加邢增索引请求至队列
        /// </summary>
        /// <param name="book"></param>
        public void Add(Books book)
        {
            PageViewMode bvm = new PageViewMode();
            bvm.URL = book.Id.ToString();
            bvm.Title = book.Title;
            bvm.IT = IndexType.Insert;
            bvm.Content = book.ContentDescription;
            pageQueue.Enqueue(bvm);
        }
        /// <summary>
        /// 删除Pages表信息时 添加删除索引请求至队列
        /// </summary>
        /// <param name="bid"></param>
        public void Del(string url)
        {
            PageViewMode bvm = new PageViewMode();
            bvm.URL = url;
            bvm.IT = IndexType.Delete;
            pageQueue.Enqueue(bvm);
        }
        /// <summary>
        /// 修改Pages表信息时 添加修改索引(实质上是先删除原有索引 再新增修改后索引)请求至队列
        /// </summary>
        /// <param name="page"></param>
        public void Mod(Books page)
        {
            PageViewMode bvm = new PageViewMode();
            bvm.URL = page.Id.ToString();
            bvm.Title = page.Title;
            bvm.IT = IndexType.Modify;
            bvm.Content = page.ContentDescription;
            pageQueue.Enqueue(bvm);
        }

        public void StartNewThread()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(QueueToIndex));
        }

        //定义一个线程 将队列中的数据取出来 插入索引库中
        private void QueueToIndex(object para)
        {
            while (true)
            {
                if (pageQueue.Count > 0)
                {
                    CRUDIndex();
                }
                else
                {
                    Thread.Sleep(3000);
                }
            }
        }
        /// <summary>
        /// 更新索引库操作
        /// </summary>
        private void CRUDIndex()
        {
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
            bool isExist = IndexReader.IndexExists(directory);
            if (isExist)
            {
                if (IndexWriter.IsLocked(directory))
                {
                    IndexWriter.Unlock(directory);
                }
            }
            IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isExist, IndexWriter.MaxFieldLength.UNLIMITED);
            while (pageQueue.Count > 0)
            {
                Document document = new Document();
                PageViewMode page = pageQueue.Dequeue();
                if (page.IT == IndexType.Insert)
                {
                    document.Add(new Field("id", page.URL.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("title", page.Title, Field.Store.YES, Field.Index.ANALYZED,
                                           Field.TermVector.WITH_POSITIONS_OFFSETS));
                    document.Add(new Field("content", page.Content, Field.Store.YES, Field.Index.ANALYZED,
                                           Field.TermVector.WITH_POSITIONS_OFFSETS));
                    writer.AddDocument(document);
                }
                else if (page.IT == IndexType.Delete)
                {
                    writer.DeleteDocuments(new Term("id", page.URL.ToString()));
                }
                else if (page.IT == IndexType.Modify)
                {
                    //先删除 再新增
                    writer.DeleteDocuments(new Term("id", page.URL.ToString()));
                    document.Add(new Field("id", page.URL.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                    document.Add(new Field("title", page.Title, Field.Store.YES, Field.Index.ANALYZED,
                                           Field.TermVector.WITH_POSITIONS_OFFSETS));
                    document.Add(new Field("content", page.Content, Field.Store.YES, Field.Index.ANALYZED,
                                           Field.TermVector.WITH_POSITIONS_OFFSETS));
                    writer.AddDocument(document);
                }
            }
            writer.Close();
            directory.Close();
        }
    }

    public class PageViewMode
    {
        public string URL
        {
            get;
            set;
        }
        public string Title
        {
            get;
            set;
        }
        public string Content
        {
            get;
            set;
        }
        public IndexType IT
        {
            get;
            set;
        }
    }
    //操作类型枚举
    public enum IndexType
    {
        Insert,
        Modify,
        Delete
    }
}