// StringLibrary.cs
// Copyright (c) 2016 Bentley Systems, Incorporated. All Rights Reserved.

using System;
using System.Globalization;
using System.Windows;
using System.Collections.Generic;
using Haestad.Support.Library;
using Haestad.Support.Support;

namespace Haestad.Framework.UI.Integration
{
    /// <summary>
    /// Class provides general utility methods for dealing with strings.
    /// </summary>
    internal sealed class StringLibrary
    {
        #region Internal Static Methods

        internal static string CleanTextResource(string resourceText)
        {
            string cleanResourceText = resourceText;
            cleanResourceText = Haestad.Support.Library.StringLibrary.StripEllipsis(cleanResourceText);
            cleanResourceText = cleanResourceText.Replace("&", String.Empty);
            return cleanResourceText;
        }

        // Note: <whar> Wrapping this commonly used method to avoid having to edit all references and redirect to Haestad.Support.Library.StringLibrary.
        internal static bool IsBlank(string text)
        {
            return Haestad.Support.Library.StringLibrary.IsBlank(text);
        }

        /// <summary>
        /// Method answers whether the actual label is a reduced word version of the full label.
        /// e.g., "Options" is a word subset of "Calculation Options".
        /// "PRV" is NOT a reduced word version of "Pressure Reducing Valve"; it is an abbreviation.
        /// </summary>
        /// <param name="actualLabel">The actual localized UIElement label.</param>
        /// <param name="fullLabel">The full localized command label.</param>
        /// <returns></returns>
        internal static bool IsWordSubsetOfFullLocalizedLabel(string actualLabel, string fullLabel)
        {
            if (actualLabel == fullLabel)
                return false;

            if (actualLabel.Length >= fullLabel.Length)
                return false;

            string lowerCaseActualLabel = actualLabel.ToLowerInvariant();
            string lowerCaseFullLabel = fullLabel.ToLowerInvariant();

            return lowerCaseFullLabel.Contains(lowerCaseActualLabel);
        }

        /// <summary>
        ///  Method answers whether the actual label is an alternate short representation of the full label, but that is NOT a word subset,
        ///  or basically anything that's shorter than the full label, and not comprised of one or more full words from the full label.
        ///  This keeps it as language agnostic as possible.
        /// e.g., "Options" is a word subset of "Calculation Options" and not an alternative short representation.
        /// "PRV" is an alternate short representation of "Pressure Reducing Valve".
        /// "VSP Battery" is an alternate short representation of "Variable Speed Pump Battery".
        /// "Backgrounds" is an alternate short representation of "Background Layers".
        /// "*" is an alternate short representation of "Asterisk".
        /// </summary>
        /// <param name="actualLabel">The actual localized UIElement label.</param>
        /// <param name="fullLabel">The full localized command label.</param>
        /// <returns></returns>
        internal static bool IsAlternateShortRepresentationOfFullLocalizedLabel(string actualLabel, string fullLabel)
        {
            if (Haestad.Support.Library.StringLibrary.IsBlank(actualLabel))
                return false;

            if (Haestad.Support.Library.StringLibrary.IsBlank(fullLabel))
                return false;

            if (fullLabel == String.Empty)
                return false;

            string lowerCaseActualLabel = actualLabel.ToLowerInvariant();
            string lowerCaseFullLabel = fullLabel.ToLowerInvariant();

            if (lowerCaseActualLabel == lowerCaseFullLabel)
                return false;

            if (lowerCaseActualLabel.Length >= lowerCaseFullLabel.Length)
                return false;

            if (lowerCaseFullLabel.Contains(lowerCaseActualLabel))
                return false;

            return true;
        }

        internal static string GetLabelWithMissingWords(string actualLabel, string fullLabel)
        {
            IList<string> actualLabelWords = GetWords(actualLabel);
            IList<string> fullLabelWords = GetWords(fullLabel);

            if (actualLabelWords.Count == 1)
                return GetLabelWithMissingWordsForSingleWordActual(actualLabelWords, fullLabelWords);
            else if (actualLabelWords.Count >= 2)
            {
                int indexOfFirstWordInCommon = 0;
                for (int i = 0; i < fullLabelWords.Count; ++i)
                {
                    if (String.Compare(actualLabelWords[0], fullLabelWords[i], true) == 0)
                    {
                        indexOfFirstWordInCommon = i;
                        break;
                    }
                }

                for (int i = 0; i < actualLabelWords.Count; ++i)
                    fullLabelWords.RemoveAt(indexOfFirstWordInCommon);

                fullLabelWords.Insert(indexOfFirstWordInCommon, actualLabel);

                actualLabelWords = new List<string>(1);
                actualLabelWords.Add(actualLabel);

                return GetLabelWithMissingWordsForSingleWordActual(actualLabelWords, fullLabelWords);
            }

            return String.Empty;
        }

        // TODO 0: Unit tests
        internal static IList<string> GetWords(string text)
        {
            string[] wordArray = Haestad.Support.Library.StringLibrary.GetTokens(text, new char[] { SPACE_CHAR });
            IList<string> words = new List<string>(wordArray.Length);
            foreach (string word in wordArray)
                words.Add(word);
            return words;
        }
        #endregion

        #region Private Static Methods
        private static string GetLabelWithMissingWordsForSingleWordActual(IList<string> actualLabelWords , IList<string> fullLabelWords)
        {
            if (actualLabelWords.Count != 1)
                return String.Empty;

            int actualLabelIndex = 0;
            for (int i = 0; i < fullLabelWords.Count; ++i)
            {
                if (String.Compare(actualLabelWords[0], fullLabelWords[i], true) == 0)
                {
                    actualLabelIndex = i;
                    break;
                }
            }

            string wordsBefore = String.Empty;
            if (actualLabelIndex > 0)
                wordsBefore = fullLabelWords[0];

            for (int i = 1; i < actualLabelIndex; ++i)
                wordsBefore += SPACE_STRING + fullLabelWords[i];

            string wordsAfter = String.Empty;
            if (actualLabelIndex < fullLabelWords.Count - 1)
            {
                wordsAfter = fullLabelWords[actualLabelIndex + 1];
                for (int i = actualLabelIndex + 2; i < fullLabelWords.Count; ++i)
                    wordsAfter += SPACE_STRING + fullLabelWords[i];
            }

            if (wordsBefore != String.Empty)
                wordsBefore = wordsBefore.Replace(wordsBefore, TextManager.Current["hfui_RibbonSearchMissingTerm", wordsBefore]);
            if (wordsAfter != String.Empty)
                wordsAfter = wordsAfter.Replace(wordsAfter, TextManager.Current["hfui_RibbonSearchMissingTerm", wordsAfter]);

            return (wordsBefore != String.Empty ? wordsBefore + SPACE_STRING : String.Empty)
                + actualLabelWords[0] +
                (wordsAfter != String.Empty ? SPACE_STRING + wordsAfter : String.Empty);
        }
        #endregion

        #region Private Constants
        private const string SPACE_STRING = " ";
        private const char SPACE_CHAR = ' ';
        #endregion

    }
}
