using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

using CMS.SiteProvider;
using CMS.EventLog;
using CMS.SettingsProvider;
using CMS.DataEngine;
using CMS.GlobalHelper;
using CMS.MediaLibrary;
using CMS.IO;

using Lucene.Net.Index;
using Lucene.Net.Documents;

using org.pdfbox.pdmodel;
using org.pdfbox.util;

/// <summary>
/// Summary description for MyMediaSearchHelper
/// </summary>
public class MyMediaSearchHelper
{
    #region "Constants"

    /// <summary>
    /// Code name for my custom media index.
    /// </summary>
    public const string MYMEDIASEARCH_NAME = "MyMediaIndex";

    /// <summary>
    ///  Name of custom id field in iDocument. This is necessary for delete index item operation.
    /// </summary>
    public const string CUSTOM_ID_FIELD = "_myid";


    /// <summary>
    ///  Name of custom update status.
    /// </summary>
    public const string MYMEDIAINDEX_TASK_TYPE_UPDATE = "MyMediaIndex_UPDATE";


    /// <summary>
    ///  Custom ready task status.
    /// </summary>
    public const string MYMEDIAINDEX_STATUS_READY = "MyMediaIndex_READY";


    /// <summary>
    ///  Custom process task status.
    /// </summary>
    public const string MYMEDIAINDEX_STATUS_PROCESS = "MyMediaIndex_PROCESS";


    /// <summary>
    /// Taskindexer will retrieve search tasks from database by count of 10.
    /// </summary>
    public const int TASK_INDEXER_RETRIEVE_ROWS_COUNT = 10;

    #endregion


    #region "Helper methods"

    /// <summary>
    /// Implementation of get content method.
    /// </summary>
    /// <param name="mfi">MediaFileInfo</param>
    public static string GetContent(MediaFileInfo mfi)
    {
        if (mfi != null)
        {
            // Get file location
            string path = MediaFileInfoProvider.GetMediaFilePath(mfi.FileLibraryID, mfi.FilePath);

            try
            {
                switch (mfi.FileExtension.ToLower())
                {
                    case ".pdf":
                        
                        PDDocument doc = PDDocument.load(path);
                        PDFTextStripper stripper = new PDFTextStripper();
                        return SearchHelper.HtmlToPlainText(stripper.getText(doc));
                    case ".txt":
                        
                        FileInfo fi = FileInfo.New(path);
                        return SearchHelper.HtmlToPlainText(fi.OpenText().ReadToEnd());
                    default:
                        
                        return "";
                }
            }
            catch (Exception ex)
            {
                EventLogProvider ep = new EventLogProvider();
                ep.LogEvent("Smart search", "UpdateContentField", ex);
                return "";
            }
        }
        return "";
    }
    

    /// <summary>
    /// Implementation of Update index item method.
    /// </summary>
    /// <param name="mfi">MediaFileInfo</param>
    /// <param name="sii">SearchIndexInfo</param>
    public static void UpdateIndexItem(MediaFileInfo mfi, SearchIndexInfo sii)
    {
        if (mfi != null && sii != null)
        {
            // Get Document object 
            Document iDoc = MyMediaSearchHelper.CreateDoc(mfi);
           
            // Update custom smart search index
            SearchHelper.Update(iDoc, sii);
        }
    }


    /// <summary>
    /// Implementation of GetMediaFileUrl method.
    /// </summary>
    /// <param name="mfi">MediaFileInfo</param>
    public static string GetMediaFileUrl(MediaFileInfo mfi)
    {
        // Get Site info
        SiteInfo si = SiteInfoProvider.GetSiteInfo(mfi.FileSiteID);
        // Get media library info
        MediaLibraryInfo lfi = MediaLibraryInfoProvider.GetMediaLibraryInfo(mfi.FileLibraryID);

        if (lfi != null && si != null)
        {
            return MediaFileURLProvider.GetMediaFileUrl(mfi, si.SiteName, lfi.LibraryFolder);
        }

        return MediaFileInfoProvider.GetMediaFileUrl(mfi.FileGUID, mfi.FileName);
    }


    /// <summary>
    /// Implementation of create document method.
    /// </summary>
    /// <param name="mfi">MediaFileInfo</param>
    public static Document CreateDoc(MediaFileInfo mfi)
    {
        // Get conetnt of the media file
        string fileContent = MyMediaSearchHelper.GetContent(mfi);

        // Creates a new Lucene.Net search document for the current text file.
        Document doc = SearchHelper.CreateDocument(SearchHelper.CUSTOM_SEARCH_INDEX, mfi.FileID.ToString(), SearchHelper.INVARIANT_FIELD_VALUE, mfi.FileCreatedWhen, SearchHelper.INVARIANT_FIELD_VALUE);

        // Adds a content field. The value of this field is used for the search result excerpt.
        SearchHelper.AddField(doc, SearchHelper.CUSTOM_CONTENT, TextHelper.LimitLength(fileContent, 200), true, false);

        // Prepare searchable content field
        StringBuilder sb = new StringBuilder();
        sb.Append(mfi.FileTitle);
        sb.Append(" ");
        sb.Append(mfi.FileDescription);
        sb.Append(" ");
        sb.Append(mfi.FileCustomData);
        sb.Append(" ");
        sb.Append(mfi.FileExtension);
        sb.Append(" ");
        sb.Append(mfi.FileMimeType);
        sb.Append(" ");
        sb.Append(mfi.FileName);
        sb.Append(" ");
        sb.Append(fileContent);

        // Adds a content field. This field is processed when the search looks for matching results.
        SearchHelper.AddField(doc, SearchHelper.CONTENT_FIELD, SearchHelper.HtmlToPlainText(sb.ToString()), false, true);

        // Adds a custom id field for delete index item operation
        // Unique custom field of document in all custom indexes for delete operation
        SearchHelper.AddField(doc, MyMediaSearchHelper.CUSTOM_ID_FIELD, doc.Get(SearchHelper.ID_FIELD), true, false);

        // Adds a title field. The value of this field is used for the search results title.
        SearchHelper.AddField(doc, SearchHelper.CUSTOM_TITLE, mfi.FileName, true, false);

        // Adds a date field. The value of this field is used for the date in the search results.
        SearchHelper.AddField(doc, SearchHelper.CUSTOM_DATE, mfi.FileCreatedWhen, true, false);

        // Adds a url field. The value of this field is used for link urls in the search results.
        SearchHelper.AddField(doc, SearchHelper.CUSTOM_URL, GetMediaFileUrl(mfi), true, false);

        return doc;
    }
        
    #endregion
}