using System.Collections;
using System.Text.RegularExpressions;
using CommunityServer.Components;
//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

namespace CommunityServer
{
    public class SearchTerms
    {
        public string[] And;
        public string[] Or;

		public bool HasTerms
		{
			get
			{
				return (And != null && And.Length > 0) || (Or != null && Or.Length > 0);
			}
		}

        #region Terms
        public static SearchTerms GetSearchTerms(string searchTerms)
        {
            SearchTerms st = new SearchTerms();
            if(Globals.IsNullorEmpty(searchTerms))
                return st;

            ArrayList searchKeywords;
            //bool performLikeMatch = false; // Never Used
            string[] andTerms;
            string[] orTerms;

            // Clean the search terms
            //
            searchTerms = Regex.Replace(searchTerms, "[^\\w]", " ", RegexOptions.Compiled | RegexOptions.Multiline);

            // Tokenize the search terms and determine if we need to perform partial match
            //
            if (searchTerms.IndexOf("*") != 0) 
            {
                //performLikeMatch = false;
                searchKeywords = TokenizeKeywords(searchTerms, true);
            } 
            else 
            {
                //performLikeMatch = true;
                searchKeywords = TokenizeKeywords(searchTerms, false);
            }

            // Get the terms divided into and/or sets
            //
            GetAndOrKeywords (searchKeywords, out andTerms, out orTerms);
            
            st.And = andTerms;
            st.Or = orTerms;

            return st;
        }
        #endregion

        #region Get AND/OR Keywords
        // *********************************************************************
        //  GetAndOrKeywords
        //
        /// <summary>
        /// Private helper function to break tokenized search terms into the
        /// and and or terms used in the search.
        /// </summary>
        /// 
        // ********************************************************************/
        private static void GetAndOrKeywords (ArrayList searchTerms, out string[] andTermsOut, out string[] orTermsOut) 
        {
            ArrayList andTerms = new ArrayList();
            ArrayList orTerms = new ArrayList();
            bool buildingORterm = false;
            int OR = "||".GetHashCode();
            int AND = "&&".GetHashCode();

            // Loop through all the tokens
            //
            foreach (int term in searchTerms) 
            {

                if (term == OR) 
                {

                    // Found an OR token, do we have any items in the AND ArrayList?
                    //
                    if (andTerms.Count > 0) 
                    {
                        orTerms.Add(andTerms[andTerms.Count - 1]);
                        andTerms.Remove(andTerms[andTerms.Count - 1]);
                        buildingORterm = true;
                    }

                } 
                else if (buildingORterm) 
                {

                    // Closing statement for an OR term
                    orTerms.Add(term);
                    buildingORterm = false;

                } 
                else if (term == AND) 
                {

                    // ignore

                } 
                else 
                {

                    andTerms.Add(term);

                }

            }


            andTermsOut =  ArrayListToStringArray(andTerms);
            orTermsOut =  ArrayListToStringArray(orTerms);

        }

        static string[] ArrayListToStringArray (ArrayList list) 
        {
            string[] s = new string[list.Count];

            for (int i = 0; i < list.Count; i++)
                s[i] = list[i].ToString();

            return s;
        }

        #endregion

        #region TokenizeKeywords
        private static ArrayList TokenizeKeywords (string searchTerms, bool toHashcode) 
        {
            ArrayList newWords = new ArrayList();
            ArrayList searchWords = new ArrayList();
            string[] words;

            // Clean the search terms
            //
            words = CleanSearchTerms(searchTerms);

            // Do these words already exist?
            foreach (string word in words) 
            {
                string wordLowerCase = word.ToLower();

                int wordHashCode = wordLowerCase.GetHashCode();

                // OR code
                if (wordHashCode == 5861509)
                    searchWords.Add(wordHashCode);

                // Only take words larger than 2 characters
                //
                if (wordLowerCase.Length > 2) 
                {

                    // Do we need to convert words to hash codes
                    //
                    if (toHashcode) 
                    {
                        searchWords.Add(wordHashCode);
                    } 
                    else 
                    {
                        searchWords.Add(word);
                    }

                }

            }

            return searchWords;

        }
        #endregion

        public static string[] CleanSearchTerms(string searchTerms) 
        {
            // Force the searchTerms to lower case
            //
            searchTerms = searchTerms.ToLower();

            // Strip any markup characters
            //
            searchTerms = Transforms.StripHtmlXmlTags(searchTerms);

            // Remove non-alpha/numeric characters
            //
            searchTerms = Regex.Replace(searchTerms, "[^\\w]", " ", RegexOptions.Compiled | RegexOptions.Multiline);

            // Replace special words with symbols
            //
            searchTerms = Regex.Replace(searchTerms, "\\bor\\b", "||", RegexOptions.Compiled | RegexOptions.Multiline);
            searchTerms = Regex.Replace(searchTerms, "\\band\\b", "&&", RegexOptions.Compiled | RegexOptions.Multiline);

            // Finally remove any extra spaces from the string
            //
            searchTerms = Regex.Replace(searchTerms, " {1,}", " ", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline); 


            return searchTerms.Split(' ');
        }
    }
}