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>
/// Sample of custom smart search index. 
/// In this example media library files from specified (if not all files from all media libraries are indexed) media library are indexed.
/// </summary>
public class MyMediaSearchIndex : ICustomSearchIndex
{
    #region ICustomSearchIndex Members

    /// <summary>
    /// Implementation of rebuild method.
    /// </summary>
    /// <param name="srchInfo">Search index info</param>
    public void Rebuild(SearchIndexInfo srchInfo)
    {
        // Check whether index info object is defined
        if (srchInfo != null)
        {
            // Get index writer for current index
            IndexWriter iw = srchInfo.GetWriter(true);

            // Check whether writer is defined
            if (iw != null)
            {
                try
                {
                    //Check whether exist index settings
                    if ((srchInfo.IndexSettings != null))
                    {
                        // Get settings info
                        SearchIndexSettingsInfo sisi = srchInfo.IndexSettings.Items[SearchHelper.CUSTOM_INDEX_DATA];
                        if (sisi != null)
                        {
                            DataClassInfo dci = DataClassInfoProvider.GetDataClass(PredefinedObjectType.MEDIAFILE);
                            if (dci != null)
                            {
                                // Get primary key
                                string primaryKey = SqlGenerator.GetPKName(dci.ClassXmlSchema);

                                if (!String.IsNullOrEmpty(primaryKey))
                                {
                                    // Get custom data from settings info
                                    string whereCondition = Convert.ToString(sisi.GetValue("CustomData"));
                                    
                                    string queryName = dci.ClassName + ".selectall";
                                    string idColumn = Convert.ToString(primaryKey);
                                    int batchSize = srchInfo.IndexBatchSize;
                                    bool multiplePKs = idColumn.Contains(";");

                                    // Last item id
                                    int lastId = 0;

                                    // Documents collection
                                    List<Document> documents = null;

                                    // Get forum iDocuments
                                    while ((documents != null) || (lastId == 0))
                                    {
                                        documents = null;

                                        DataSet ds = null;
                                        if (!multiplePKs)
                                        {
                                            // Load top n rows for current object
                                            // Select from last item
                                            string scopeWhere = SqlHelperClass.AddWhereCondition(idColumn + " > " + lastId, whereCondition);
                                            ds = ConnectionHelper.ExecuteQuery(queryName, null, scopeWhere, idColumn, batchSize, null);
                                        }
                                        else
                                        {
                                            // If the table has multiple PKs, disable the batch size
                                            ds = ConnectionHelper.ExecuteQuery(queryName, null, whereCondition, "", -1, null);
                                        }
                                        if (!DataHelper.DataSourceIsEmpty(ds))
                                        {
                                            documents = new List<Document>();
                                            foreach (DataRow dr in ds.Tables[0].Rows)
                                            {
                                                // Get MediaFileInfo
                                                MediaFileInfo mfi = new MediaFileInfo(dr);
                                                // Create document from MediaFileInfo
                                                Document doc = MyMediaSearchHelper.CreateDoc(mfi);
                                                // Add document object to collection
                                                documents.Add(doc);
                                            }
                                        }

                                        if ((documents != null) && (documents.Count > 0))
                                        {
                                            // Get last ID  (document id)
                                            lastId = ValidationHelper.GetInteger(documents[documents.Count - 1].Get(SearchHelper.ID_FIELD), 1);

                                            // Loop thru all iDocuments
                                            foreach (Document doc in documents)
                                            {
                                                iw.AddDocument(doc);
                                            }

                                            iw.Flush();
                                        }
                                        else
                                        {
                                            break;
                                        }

                                        // If the table has multiple PKs, disable the batch size (run the query just once)
                                        if (multiplePKs)
                                        {
                                            break;
                                        }
                                    }
                                }

                                // Optimize index
                                srchInfo.IndexStatus = IndexStatusEnum.OPTIMIZING;

                                if (AzureHelper.IsRunningOnAzure)
                                {
                                    SearchIndexInfoProvider.SetSearchIndexInfo(srchInfo);
                                }

                                iw.Optimize();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    EventLogProvider ep = new EventLogProvider();
                    ep.LogEvent("Smart search", "rebuild", ex);

                    // Set statuses to error
                    srchInfo.IndexStatus = IndexStatusEnum.ERROR;

                    if (AzureHelper.IsRunningOnAzure)
                    {
                        SearchIndexInfoProvider.SetSearchIndexInfo(srchInfo);
                    }
                }
                finally
                {
                    if (iw != null)
                    {
                        // Close index
                        iw.Close();
                    }
                }
            }
        }
    }

    #endregion
}
