//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System.Collections;
using System.Xml;
using CommunityServer.Configuration;

namespace CommunityServer.Components.SearchBarrel
{
	/// <summary>
	/// Provides base implementation for background search indexing. Execute will walk all of the current
	/// sties and call Search.IndexPosts for each site/settingsID
	/// </summary>
    public abstract class SearchJob : IJob
    {
        public SearchJob()
        {
			
        }

        public abstract void IndexPosts (int setSize, int settingsID);

        protected abstract double CalculateWordRank (Word word, Post post, int totalBodyWords);

        /// <summary>
        /// All applications use the same SearchBarrel. This method provides default access to it.
        /// </summary>
        public void InsertIntoSearchBarrel(Hashtable words, Post post, int settingsID, int totalBodyWords)
        {
            foreach(int key in words.Keys)
            {
                Word w = words[key] as Word;
                w.Weight = CalculateWordRank(w,post,totalBodyWords);
            }

            CommonDataProvider dp = CommonDataProvider.Instance(); 
            dp.InsertIntoSearchBarrel(words, post, settingsID);
        }

        protected void IndexPosts(int settingsID)
        {
            //Set the context for this thread
            //CSContext.CreateEmptyContext();
			//Creates a content to used through out the execution of a sites tasks. 
			//This context will only have access to the anonymous user, so loading sections
			//and posts much account for this (Updated from the empty context above 031406 DB)
			CSContext.Create(settingsID);
			IndexPosts(50,settingsID);
        }


        public void Execute(XmlNode node)
        {
            SiteSettingsManager.IterateSiteSettings(new SiteSettingsListIterator(this.IndexPosts));
        }
        #region static indexing

        #region Index
        // *********************************************************
        // Index
        //
        /// <summary>
        /// Populates a hashtable of words that will be entered into
        /// the forums search barrel.
        /// </summary>
        /// 
        protected static Hashtable Index (string contentToIndex, Hashtable words, WordLocation wordLocation, int settingsID) 
        {

            // Get the ignore words
            //
            Hashtable ignoreWords = GetIgnoreWords(settingsID);

            // Get a string array of the words we want to index
            //
            string[] wordsToIndex = SearchTerms.CleanSearchTerms(contentToIndex);

            // Ensure we have data to work with
            //
            if (wordsToIndex.Length == 0)
                return words;

            // Operate on each word in stringArrayOfWords
            //
            foreach (string word in wordsToIndex) 
            {

                if(word != null && word.Length >= 3)
                {
                    // Get the hash code for the word
                    //
                    int hashedWord = word.ToLower().GetHashCode();

                    // Add the word to our words Hashtable
                    //
                    if (!ignoreWords.ContainsKey(hashedWord)) 
                    {
                        if (!words.Contains(hashedWord))
                            words.Add(hashedWord, new Word(word, wordLocation));
                        else
                            ((Word) words[hashedWord]).IncrementOccurence(wordLocation);
                    }
                }
                
            }

            return words;
        }
        #endregion



        #region CleanSearchTerms helper function

        /// <summary>
        /// Retuns a hashtable of words that are ignored. Search terms are filtered with these words
        /// </summary>
        /// <returns></returns>
        static Hashtable GetIgnoreWords (int settingsID) 
        {
            string cacheKey = string.Format("SettingsID:{0}SearchIgnoreWordsTable",settingsID);

            // Do we have the item in cache?
            //
            Hashtable ignoreWords = CSCache.Get(cacheKey) as Hashtable;
            if (ignoreWords == null) 
            {

                // Create Instance of the CommonDataProvider
                //
                CommonDataProvider dp = CommonDataProvider.Instance();

                ignoreWords = dp.GetSearchIgnoreWords(settingsID);

                CSCache.Max(cacheKey, ignoreWords);

            }

            return ignoreWords;

        }
        #endregion

        #endregion
    }
}
