using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace mgaia.Utils.Text
{
    /// <summary>
    /// Classe utilizada para formatar TextMeshs
    /// </summary>
    /// <owner>Victor</owner>
    public static class TextMeshFormatter
    {
        /// <summary>
        /// Retorna o tamanho que cada caractere ocupa em determinada TextMesh
        /// </summary>
        public static Dictionary<char, float> CreateCharactersLengthDictionary(ITextMesh textMesh)
        {
            Dictionary<char, float> charactersLength = new Dictionary<char, float>();
            Constants.CHARACTERS_STRING.ForEach(c =>
            {
                charactersLength[c] = textMesh.GetEstimatedMeshBoundsForString(c.ToString()).size.x;
            });
            return charactersLength;
        }

        /// <summary>
        /// Formata um TextMesh para que ele caiba no espaço solicitado
        /// </summary>
        public static string FormatTextMesh(ITextMesh textMesh, int maxLines, float maxLineLength, bool setText)
        {
			string text = textMesh.Text;

			Assert.AssertTrue(text.GetNumberOfLines() <= maxLines, "The number of lines in the source text exceeds the value of the maxLines parameter.");
			
			Vector3 scaleDecrement = textMesh.Scale * 0.05f;
			int iterationNumber = 0;
			int currentIndex = 0;
			float totalLength = 0.0f;
			int lineQtt = int.MaxValue;
			int previousBlankIndex = -1;
			Dictionary<char, float> charactersLength = CreateCharactersLengthDictionary(textMesh);
			while ((lineQtt > maxLines) || (totalLength > maxLineLength))
			{
				if (iterationNumber > 0)
				{
					text = textMesh.Text;
					textMesh.Scale -= scaleDecrement;
				}
				currentIndex = 0;
				totalLength = 0.0f;
				lineQtt = 1;
				previousBlankIndex = -1;
				charactersLength = CreateCharactersLengthDictionary(textMesh);
				while (currentIndex < text.Length)
				{
					if (text[currentIndex] == Constants.Blank)
					{
						previousBlankIndex = currentIndex;
					}
					
					if (text[currentIndex] == Constants.NewLine)
					{
						totalLength = 0.0f;
						lineQtt++;
					}
					else if (charactersLength.ContainsKey(text[currentIndex]))
					{
						totalLength += charactersLength[text[currentIndex]];
					}
					else
					{
						Debug.LogWarning("Length not found for the character: " + text[currentIndex]);
					}
					if (totalLength > maxLineLength)
					{
						if (previousBlankIndex != -1)
						{
							currentIndex = previousBlankIndex;
							text = text.Substring(0, currentIndex) + Constants.NewLine + text.Substring(currentIndex + 1, text.Length - currentIndex - 1);
							totalLength = 0.0f;
							lineQtt++;
							previousBlankIndex = -1;
						}
						else
						{
							break;
						}
					}
					currentIndex++;
				}
				iterationNumber++;
			}

			textMesh.MaxChars = text.Length;

            if (setText)
            {
                textMesh.Text = text;
            }

            return text;
        }

		/// <summary>
		/// Formata um TextMesh seguindo uma template já existente nele
		/// </summary>
		public static string FormatTextMeshFollowingTemplate(ITextMesh textMesh, string newText, bool setText)
		{
			string text = textMesh.Text;

			float width = textMesh.GetEstimatedMeshBoundsForString(text).size.x;
			int numberOfLines = text.GetNumberOfLines();

			textMesh.Text = newText;

			return FormatTextMesh(textMesh, numberOfLines, width, setText);
		}
    }
}