/// <summary>
        /// Take ISearchResults from examine, create title and body summary, and return a collection of SearchResultPages
        /// </summary>
        /// <param name="AltSearchResults">
        /// Collection of search results.
        /// </param>
        /// <param name="AltSummarizer">
        /// Summarizer to format results
        /// </param>
        /// <param name="PageNumber">
        /// The current page Number
        /// </param>
        /// <param name="PageLength">
        /// Num Results per page
        /// </param>
        private static AlternateSpellingsInfo UpdateAlternateResults(AlternateSpellingsInfo AltSpellingsInfo, ISearchResults AltSearchResults, Summarizer AltSummarizer, int PageNumber, int PageLength)
        {
            //Convert from Examine Results to FullText Results
            var convertedResults = ConvertSearchResultsToFullTextResults(AltSearchResults, AltSummarizer, PageNumber).ToList();

            AltSpellingsInfo.AllResults = convertedResults;

            //Handle Paging
            var allResults   = convertedResults.ToList();
            var totalResults = allResults.Count();

            AltSpellingsInfo.TotalResults = totalResults;
            var numPages = totalResults % PageLength == 0 ? totalResults / PageLength : totalResults / PageLength + 1;

            AltSpellingsInfo.NumOfPages = numPages;

            var allPages = new List <SearchResultPage>();

            //divide results into pages
            if (PageLength > 0)
            {
                var toSkip = 0;
                for (int i = 0; i < numPages; i++)
                {
                    var page = new SearchResultPage();

                    page.PageNum       = i + 1;
                    toSkip             = i * PageLength;
                    page.Results       = allResults.Skip(toSkip).Take(PageLength);
                    page.ResultsOnPage = page.Results.Count();
                    page.FirstResult   = toSkip + 1;

                    var lastResult = toSkip + PageLength;
                    if (lastResult > totalResults)
                    {
                        lastResult = totalResults;
                    }
                    page.LastResult = lastResult;

                    allPages.Add(page);
                }
            }

            AltSpellingsInfo.Pages = allPages;

            return(AltSpellingsInfo);
        }
        /// <summary>
        /// Main Helper Search function, the laundry list of parameters are documented more fully in FullTextSearch.xslt
        /// Basically this constructs a search object and a highlighter object from the parameters, then calls another
        /// function to return search results as SearchResultsCollection.
        /// </summary>
        /// <param name="SearchType">MultiRelevance, MultiAnd, etc.</param>
        /// <param name="SearchTerm">The search terms as entered by user</param>
        /// <param name="TitleProperties">A list of umbraco properties, comma separated, to be searched as the page title</param>
        /// <param name="BodyProperties">A list of umbraco properties, comma separated, to be searched as the page body</param>
        /// <param name="RootNodes">Return only results under these nodes, set to blank or -1 to search all nodes</param>
        /// <param name="TitleLinkProperties">Umbraco properties, comma separated, to use in forming the (optionally highlighted) title</param>
        /// <param name="SummaryProperties">Umbraco properties, comma separated, to use in forming the (optionally highlighted) summary text</param>
        /// <param name="UseHighlighting">Enable context highlighting(note this can slow things down)</param>
        /// <param name="SummaryLength">Number of characters in the summary text</param>
        /// <param name="PageNumber">Page number of results to return</param>
        /// <param name="PageLength">Number of results on each page, zero disables paging and returns all results</param>
        /// <param name="Fuzzieness">Amount 0-1 to "fuzz" the search, return non exact matches</param>
        /// <param name="Wildcard">Add wildcard to the end of search term. Doesn't work together with fuzzyness</param>
        /// <param name="AlternateSpellingSuggestions">If the AlternateSpellings Index is set up, the number of alternates to return (0 to disable)</param>
        /// <returns></returns>
        public static SearchResultsCollection Search(string SearchType, string SearchTerm, string TitleProperties, string BodyProperties, string RootNodes, string TitleLinkProperties, string SummaryProperties, int UseHighlighting, int SummaryLength, int PageNumber = 0, int PageLength = 0, string Fuzzieness = "1.0", int Wildcard = 0, int AlternateSpellingSuggestions = 0)
        {
            //Initialize
            var resultsColl = new SearchResultsCollection();

            resultsColl.KeywordsQuery        = SearchTerm;
            resultsColl.ConfigResultsPerPage = PageLength;

            // Measure time taken. This could be done more neatly, but this is more accurate
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            // Check search terms were actually entered
            if (string.IsNullOrEmpty(SearchTerm))
            {
                resultsColl.IsError   = true;
                resultsColl.ErrorCode = "NoTerms";
                resultsColl.ErrorMsg  = "You must enter a search term";

                return(resultsColl);
            }

            // Setup initial search parameters
            resultsColl.SearchParameters = SetupSearchParameters(SearchTerm, TitleProperties, BodyProperties, RootNodes, Fuzzieness, Wildcard);

            //Setup summarizer parameters
            resultsColl.SummarizerParameters = SetupSummariserParameters(SearchTerm, TitleLinkProperties, SummaryProperties, SummaryLength, Fuzzieness, Wildcard);

            // Create summarizer according to highlighting option
            resultsColl.Summarizer = SetupSummariser(resultsColl.SummarizerParameters, UseHighlighting);

            //Do Search, get results
            var searchResults = GetSearchResults(resultsColl.SearchParameters, SearchType);

            //Alternate Spellings?
            var altSpellInfo = new AlternateSpellingsInfo();

            if (AlternateSpellingSuggestions > 0)
            {
                altSpellInfo.AlternateSpellingsInUse     = true;
                altSpellInfo.SearchTermIsMultiWordPhrase = SearchTerm.Contains(' ');

                var alternateSpellingTool = AlternateSpellingTool.Instance;

                var checkedTerms    = SearchTerm.Split(' ').Select(t => alternateSpellingTool.GetBestMatchWord(t));
                var alternatePhrase = String.Join(" ", checkedTerms);
                altSpellInfo.BestMatchWord = alternatePhrase;

                if (!altSpellInfo.SearchTermIsMultiWordPhrase)
                {
                    var allWords = alternateSpellingTool.GetAlternateWordList(SearchTerm, AlternateSpellingSuggestions);
                    altSpellInfo.AlternateWordSuggestions = allWords;
                }

                //Re-run search with best match?
                if (!searchResults.Any())
                {
                    //Do Search, get results
                    var altSummariserParams = SetupSummariserParameters(altSpellInfo.BestMatchWord, TitleLinkProperties, SummaryProperties, SummaryLength, Fuzzieness, Wildcard);
                    var altSummarizer       = SetupSummariser(altSummariserParams, UseHighlighting);
                    var altSearchParams     = SetupSearchParameters(altSpellInfo.BestMatchWord, TitleProperties, BodyProperties, RootNodes, Fuzzieness, Wildcard);
                    var altSearchResults    = GetSearchResults(altSearchParams, SearchType);
                    altSpellInfo = UpdateAlternateResults(altSpellInfo, altSearchResults, altSummarizer, PageNumber, PageLength);
                }
            }

            //Pass ISearchResults to updater function
            resultsColl = UpdateWithResults(resultsColl, searchResults, PageNumber, stopwatch);
            resultsColl.AlternateSpellingsInfo = altSpellInfo;

            return(resultsColl);
        }