using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Core.SubtitleFormats;
using Nikse.SubtitleEdit.Logic;
using Nikse.SubtitleEdit.Logic.Config;
using Nikse.SubtitleEdit.Logic.Config.Language;
using Nikse.SubtitleEdit.Logic.Media;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Threading.Tasks;

namespace Nikse.SubtitleEdit.Features.Files.Statistics;

public partial class StatisticsViewModel : ObservableObject
{

    public class StingOrdinalComparer : IEqualityComparer<string>, IComparer<string>
    {
        public bool Equals(string? x, string? y)
        {
            if (x == null)
            {
                return y == null;
            }

            return x.Equals(y, StringComparison.Ordinal);
        }

        public int GetHashCode(string x)
        {
            return x.GetHashCode();
        }

        public int Compare(string? x, string? y)
        {
            return string.CompareOrdinal(x, y);
        }
    }

    [ObservableProperty] private string _title;
    [ObservableProperty] private string _textGeneral;
    [ObservableProperty] private string _textMostUsedWords;
    [ObservableProperty] private string _textMostUsedLines;

    public Window? Window { get; internal set; }
    public bool OkPressed { get; private set; }

    public IFileHelper _fileHelper;

    private Subtitle _subtitle;
    private SubtitleFormat _format;
    private readonly LanguageStatistics _l;
    private int _totalWords;
    private const string WriteFormat = @"File generated by: Subtitle Edit
https://www.nikse.dk/subtitleedit/
https://github.com/SubtitleEdit/subtitleedit

============================= General =============================
{0}

============================= Most Used Words =============================
{1}

============================= Most Used Lines =============================
{2}";
    private string _fileName;

    private static readonly char[] ExpectedChars = { '♪', '♫', '"', '(', ')', '[', ']', ' ', ',', '!', '?', '.', ':', ';', '-', '_', '@', '<', '>', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '،', '؟', '؛' };
    public StatisticsViewModel(IFileHelper fileHelper)
    {
        _fileHelper = fileHelper;

        Title = string.Empty;
        TextGeneral = string.Empty;
        TextMostUsedWords = string.Empty;
        TextMostUsedLines = string.Empty;

        _subtitle = new Subtitle();
        _format = new SubRip();
        _l = Se.Language.File.Statistics;
        _fileName = string.Empty;
    }

    [RelayCommand]
    private void Ok()
    {
        OkPressed = true;
        Close();
    }

    [RelayCommand]
    private void Cancel()
    {
        Close();
    }

    [RelayCommand]
    private async Task Export()
    {
        var suggestFileName = "statistics.txt";
        if (!string.IsNullOrEmpty(_fileName))
        {
            suggestFileName = System.IO.Path.GetFileNameWithoutExtension(_fileName) + "_statistics.txt";
        }

        var textFileName = await _fileHelper.PickSaveFile(Window!, ".txt", suggestFileName, Se.Language.General.SaveFileAsTitle);
        if (string.IsNullOrEmpty(textFileName))
        {
            return;
        }

        var statistic = string.Format(WriteFormat, TextGeneral, TextMostUsedWords, TextMostUsedLines);
        System.IO.File.WriteAllText(textFileName, statistic);
    }

    private void Close()
    {
        Dispatcher.UIThread.Post(() =>
        {
            Window?.Close();
        });
    }

    internal void Initialize(Subtitle subtitle, SubtitleFormat format, string fileName)
    {
        _subtitle = subtitle;
        _format = format;
        _fileName = fileName;

        CalculateWordStatistics();
        CalculateGeneralStatistics();
        CalculateMostUsedLines();

        Dispatcher.UIThread.Post(() =>
        {
            if (string.IsNullOrEmpty(_fileName))
            {
                Title = _l.Title;
            }
            else
            {
                Title = string.Format(_l.TitleWithFileName, _fileName);
            }
        });
    }

    private void CalculateGeneralStatistics()
    {
        if (_subtitle == null || _subtitle.Paragraphs.Count == 0)
        {
            TextGeneral = _l.NothingFound;
            return;
        }

        var allText = new StringBuilder();
        int minimumLineLength = 99999999;
        int maximumLineLength = 0;
        long totalLineLength = 0;
        int minimumSingleLineLength = 99999999;
        int maximumSingleLineLength = 0;
        long totalSingleLineLength = 0;
        long totalSingleLines = 0;
        int minimumSingleLineWidth = 99999999;
        int maximumSingleLineWidth = 0;
        long totalSingleLineWidth = 0;
        double minimumDuration = 100000000;
        double maximumDuration = 0;
        double totalDuration = 0;
        double minimumCharsSec = 100000000;
        double maximumCharsSec = 0;
        double totalCharsSec = 0;
        double minimumWpm = 100000000;
        double maximumWpm = 0;
        double totalWpm = 0;
        var gapMinimum = double.MaxValue;
        var gapMaximum = 0d;
        var gapTotal = 0d;

        var aboveOptimalCpsCount = 0;
        var aboveMaximumCpsCount = 0;
        var aboveMaximumWpmCount = 0;
        var belowMinimumDurationCount = 0;
        var aboveMaximumDurationCount = 0;
        var aboveMaximumLineLengthCount = 0;
        var aboveMaximumLineWidthCount = 0;
        var belowMinimumGapCount = 0;

        foreach (var p in _subtitle.Paragraphs)
        {
            allText.Append(p.Text);

            var len = GetLineLength(p);
            minimumLineLength = Math.Min(minimumLineLength, len);
            maximumLineLength = Math.Max(len, maximumLineLength);
            totalLineLength += len;

            var duration = p.DurationTotalMilliseconds;
            minimumDuration = Math.Min(duration, minimumDuration);
            maximumDuration = Math.Max(duration, maximumDuration);
            totalDuration += duration;

            var charsSec = p.GetCharactersPerSecond();
            minimumCharsSec = Math.Min(charsSec, minimumCharsSec);
            maximumCharsSec = Math.Max(charsSec, maximumCharsSec);
            totalCharsSec += charsSec;

            var wpm = p.WordsPerMinute;
            minimumWpm = Math.Min(wpm, minimumWpm);
            maximumWpm = Math.Max(wpm, maximumWpm);
            totalWpm += wpm;

            var next = _subtitle.GetParagraphOrDefault(_subtitle.GetIndex(p) + 1);
            if (next != null)
            {
                var gap = next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds;
                if (gap < gapMinimum)
                {
                    gapMinimum = gap;
                }

                if (gap > gapMaximum)
                {
                    gapMaximum = gap;
                }

                if (gap < Configuration.Settings.General.MinimumMillisecondsBetweenLines)
                {
                    belowMinimumGapCount++;
                }

                gapTotal += gap;
            }

            foreach (var line in p.Text.SplitToLines())
            {
                var l = GetSingleLineLength(line);
                minimumSingleLineLength = Math.Min(l, minimumSingleLineLength);
                maximumSingleLineLength = Math.Max(l, maximumSingleLineLength);
                totalSingleLineLength += l;

                if (l > Configuration.Settings.General.SubtitleLineMaximumLength)
                {
                    aboveMaximumLineLengthCount++;
                }

                if (Configuration.Settings.Tools.ListViewSyntaxColorWideLines)
                {
                    var w = GetSingleLineWidth(line);
                    minimumSingleLineWidth = Math.Min(w, minimumSingleLineWidth);
                    maximumSingleLineWidth = Math.Max(w, maximumSingleLineWidth);
                    totalSingleLineWidth += w;

                    if (w > Configuration.Settings.General.SubtitleLineMaximumPixelWidth)
                    {
                        aboveMaximumLineWidthCount++;
                    }
                }

                totalSingleLines++;
            }

            var cps = p.GetCharactersPerSecond();
            if (cps > Configuration.Settings.General.SubtitleOptimalCharactersPerSeconds)
            {
                aboveOptimalCpsCount++;
            }
            if (cps > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
            {
                aboveMaximumCpsCount++;
            }

            if (p.WordsPerMinute > Configuration.Settings.General.SubtitleMaximumWordsPerMinute)
            {
                aboveMaximumWpmCount++;
            }

            if (p.DurationTotalMilliseconds < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
            {
                belowMinimumDurationCount++;
            }
            if (p.DurationTotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
            {
                aboveMaximumDurationCount++;
            }
        }

        var sb = new StringBuilder();
        var sourceLength = _subtitle.ToText(_format).Length;
        var allTextToLower = allText.ToString().ToLowerInvariant();

        sb.AppendLine(string.Format(_l.NumberOfLinesX, _subtitle.Paragraphs.Count));
        sb.AppendLine(string.Format(_l.LengthInFormatXinCharactersY, _format.FriendlyName, sourceLength));
        sb.AppendLine(string.Format(_l.NumberOfCharactersInTextOnly, allText.ToString().CountCharacters(false)));
        sb.AppendLine(string.Format(_l.TotalDuration, new TimeCode(totalDuration).ToDisplayString()));
        sb.AppendLine(string.Format(_l.TotalCharsPerSecond, (double)allText.ToString().CountCharacters(true) / (totalDuration / TimeCode.BaseUnit)));
        sb.AppendLine(string.Format(_l.TotalWords, _totalWords));
        sb.AppendLine(string.Format(_l.NumberOfItalicTags, Utilities.CountTagInText(allTextToLower, "<i>")));
        sb.AppendLine(string.Format(_l.NumberOfBoldTags, Utilities.CountTagInText(allTextToLower, "<b>")));
        sb.AppendLine(string.Format(_l.NumberOfUnderlineTags, Utilities.CountTagInText(allTextToLower, "<u>")));
        sb.AppendLine(string.Format(_l.NumberOfFontTags, Utilities.CountTagInText(allTextToLower, "<font ")));
        sb.AppendLine(string.Format(_l.NumberOfAlignmentTags, Utilities.CountTagInText(allTextToLower, "{\\an")));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.LineLengthMinimum, minimumLineLength) + " (" + GetIndicesWithLength(minimumLineLength) + ")");
        sb.AppendLine(string.Format(_l.LineLengthMaximum, maximumLineLength) + " (" + GetIndicesWithLength(maximumLineLength) + ")");
        sb.AppendLine(string.Format(_l.LineLengthAverage, (double)totalLineLength / _subtitle.Paragraphs.Count));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.LinesPerSubtitleAverage, (double)totalSingleLines / _subtitle.Paragraphs.Count));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.SingleLineLengthMinimum, minimumSingleLineLength) + " (" + GetIndicesWithSingleLineLength(minimumSingleLineLength) + ")");
        sb.AppendLine(string.Format(_l.SingleLineLengthMaximum, maximumSingleLineLength) + " (" + GetIndicesWithSingleLineLength(maximumSingleLineLength) + ")");
        sb.AppendLine(string.Format(_l.SingleLineLengthAverage, (double)totalSingleLineLength / totalSingleLines));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.SingleLineLengthExceedingMaximum, Configuration.Settings.General.SubtitleLineMaximumLength, aboveMaximumLineLengthCount, ((double)aboveMaximumLineLengthCount / _subtitle.Paragraphs.Count) * 100.0));
        sb.AppendLine();

        if (Configuration.Settings.Tools.ListViewSyntaxColorWideLines)
        {
            sb.AppendLine(string.Format(_l.SingleLineWidthMinimum, minimumSingleLineWidth) + " (" + GetIndicesWithSingleLineWidth(minimumSingleLineWidth) + ")");
            sb.AppendLine(string.Format(_l.SingleLineWidthMaximum, maximumSingleLineWidth) + " (" + GetIndicesWithSingleLineWidth(maximumSingleLineWidth) + ")");
            sb.AppendLine(string.Format(_l.SingleLineWidthAverage, (double)totalSingleLineWidth / totalSingleLines));
            sb.AppendLine();
            sb.AppendLine(string.Format(_l.SingleLineWidthExceedingMaximum, Configuration.Settings.General.SubtitleLineMaximumPixelWidth, aboveMaximumLineWidthCount, ((double)aboveMaximumLineWidthCount / _subtitle.Paragraphs.Count) * 100.0));
            sb.AppendLine();
        }

        sb.AppendLine(string.Format(_l.DurationMinimum, minimumDuration / TimeCode.BaseUnit) + " (" + GetIndicesWithDuration(minimumDuration) + ")");
        sb.AppendLine(string.Format(_l.DurationMaximum, maximumDuration / TimeCode.BaseUnit) + " (" + GetIndicesWithDuration(maximumDuration) + ")");
        sb.AppendLine(string.Format(_l.DurationAverage, totalDuration / _subtitle.Paragraphs.Count / TimeCode.BaseUnit));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.DurationExceedingMinimum, Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds / TimeCode.BaseUnit, belowMinimumDurationCount, ((double)belowMinimumDurationCount / _subtitle.Paragraphs.Count) * 100.0));
        sb.AppendLine(string.Format(_l.DurationExceedingMaximum, Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds / TimeCode.BaseUnit, aboveMaximumDurationCount, ((double)aboveMaximumDurationCount / _subtitle.Paragraphs.Count) * 100.0));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.CharactersPerSecondMinimum, minimumCharsSec) + " (" + GetIndicesWithCps(minimumCharsSec) + ")");
        sb.AppendLine(string.Format(_l.CharactersPerSecondMaximum, maximumCharsSec) + " (" + GetIndicesWithCps(maximumCharsSec) + ")");
        sb.AppendLine(string.Format(_l.CharactersPerSecondAverage, totalCharsSec / _subtitle.Paragraphs.Count));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.CharactersPerSecondExceedingOptimal, Configuration.Settings.General.SubtitleOptimalCharactersPerSeconds, aboveOptimalCpsCount, ((double)aboveOptimalCpsCount / _subtitle.Paragraphs.Count) * 100.0));
        sb.AppendLine(string.Format(_l.CharactersPerSecondExceedingMaximum, Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds, aboveMaximumCpsCount, ((double)aboveMaximumCpsCount / _subtitle.Paragraphs.Count) * 100.0));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.WordsPerMinuteMinimum, minimumWpm) + " (" + GetIndicesWithWpm(minimumWpm) + ")");
        sb.AppendLine(string.Format(_l.WordsPerMinuteMaximum, maximumWpm) + " (" + GetIndicesWithWpm(maximumWpm) + ")");
        sb.AppendLine(string.Format(_l.WordsPerMinuteAverage, totalWpm / _subtitle.Paragraphs.Count));
        sb.AppendLine();
        sb.AppendLine(string.Format(_l.WordsPerMinuteExceedingMaximum, Configuration.Settings.General.SubtitleMaximumWordsPerMinute, aboveMaximumWpmCount, ((double)aboveMaximumWpmCount / _subtitle.Paragraphs.Count) * 100.0));
        sb.AppendLine();

        if (_subtitle.Paragraphs.Count > 1)
        {
            sb.AppendLine(string.Format(_l.GapMinimum, gapMinimum) + " (" + GetIndicesWithGap(gapMinimum) + ")");
            sb.AppendLine(string.Format(_l.GapMaximum, gapMaximum) + " (" + GetIndicesWithGap(gapMaximum) + ")");
            sb.AppendLine(string.Format(_l.GapAverage, gapTotal / _subtitle.Paragraphs.Count - 1));
            sb.AppendLine();
            sb.AppendLine(string.Format(_l.GapExceedingMinimum, Configuration.Settings.General.MinimumMillisecondsBetweenLines, belowMinimumGapCount, ((double)belowMinimumGapCount / _subtitle.Paragraphs.Count) * 100.0));
            sb.AppendLine();
        }

        TextGeneral = sb.ToString().Trim();
    }

    private static int GetLineLength(Paragraph p)
    {
        return p.Text.Replace(Environment.NewLine, string.Empty).CountCharacters(Configuration.Settings.General.CpsLineLengthStrategy, false);
    }

    private static int GetSingleLineLength(string s)
    {
        return s.CountCharacters(Configuration.Settings.General.CpsLineLengthStrategy, false);
    }

    private static int GetSingleLineWidth(string s)
    {
        var textBlock = new TextBlock();
        var x = TextMeasurer.MeasureString(HtmlUtil.RemoveHtmlTags(s, true), textBlock.FontFamily.Name, (float)textBlock.FontSize);
        return (int)x.Width;
    }

    private const int NumberOfLinesToShow = 10;

    private string GetIndicesWithDuration(double duration)
    {
        var indices = new List<string>();
        for (var i = 0; i < _subtitle.Paragraphs.Count; i++)
        {
            var p = _subtitle.Paragraphs[i];
            if (Math.Abs(p.DurationTotalMilliseconds - duration) < 0.01)
            {
                if (indices.Count >= NumberOfLinesToShow)
                {
                    indices.Add("...");
                    break;
                }
                indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
            }
        }
        return string.Join(", ", indices);
    }

    private string GetIndicesWithCps(double cps)
    {
        var indices = new List<string>();
        for (var i = 0; i < _subtitle.Paragraphs.Count; i++)
        {
            var p = _subtitle.Paragraphs[i];
            if (Math.Abs(p.GetCharactersPerSecond() - cps) < 0.01)
            {
                if (indices.Count >= NumberOfLinesToShow)
                {
                    indices.Add("...");
                    break;
                }
                indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
            }
        }

        return string.Join(", ", indices);
    }

    private string GetIndicesWithWpm(double wpm)
    {
        var indices = new List<string>();
        for (var i = 0; i < _subtitle.Paragraphs.Count; i++)
        {
            var p = _subtitle.Paragraphs[i];
            if (Math.Abs(p.WordsPerMinute - wpm) < 0.01)
            {
                if (indices.Count >= NumberOfLinesToShow)
                {
                    indices.Add("...");
                    break;
                }
                indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
            }
        }

        return string.Join(", ", indices);
    }

    private string GetIndicesWithGap(double cps)
    {
        var indices = new List<string>();
        for (var i = 0; i < _subtitle.Paragraphs.Count - 1; i++)
        {
            var p = _subtitle.Paragraphs[i];
            var next = _subtitle.Paragraphs[i + 1];
            var gap = next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds;
            if (Math.Abs(gap - cps) < 0.01)
            {
                if (indices.Count >= NumberOfLinesToShow)
                {
                    indices.Add("...");
                    break;
                }
                indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
            }
        }

        return string.Join(", ", indices);
    }

    private string GetIndicesWithLength(int length)
    {
        var indices = new List<string>();
        for (var i = 0; i < _subtitle.Paragraphs.Count; i++)
        {
            var p = _subtitle.Paragraphs[i];
            if (GetLineLength(p) == length)
            {
                if (indices.Count >= NumberOfLinesToShow)
                {
                    indices.Add("...");
                    break;
                }
                indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
            }
        }
        return string.Join(", ", indices);
    }

    private string GetIndicesWithSingleLineLength(int length)
    {
        var indices = new List<string>();
        for (var i = 0; i < _subtitle.Paragraphs.Count; i++)
        {
            var p = _subtitle.Paragraphs[i];
            foreach (var line in p.Text.SplitToLines())
            {
                if (GetSingleLineLength(line) == length)
                {
                    if (indices.Count >= NumberOfLinesToShow)
                    {
                        indices.Add("...");
                        return string.Join(", ", indices);
                    }
                    indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
                    break;
                }
            }
        }
        return string.Join(", ", indices);
    }

    private string GetIndicesWithSingleLineWidth(int width)
    {
        var indices = new List<string>();
        for (int i = 0; i < _subtitle.Paragraphs.Count; i++)
        {
            var p = _subtitle.Paragraphs[i];
            foreach (var line in p.Text.SplitToLines())
            {
                if (GetSingleLineWidth(line) == width)
                {
                    if (indices.Count >= NumberOfLinesToShow)
                    {
                        indices.Add("...");
                        return string.Join(", ", indices);
                    }
                    indices.Add("#" + (i + 1).ToString(CultureInfo.InvariantCulture));
                    break;
                }
            }
        }
        return string.Join(", ", indices);
    }

    private void MostUsedWordsAdd(Dictionary<string, int> hashtable, string input)
    {
        var text = input;
        if (text.Contains("< "))
        {
            text = HtmlUtil.FixInvalidItalicTags(text);
        }

        text = StripHtmlTags(text);

        var idx = text.IndexOf("<font", StringComparison.OrdinalIgnoreCase);
        var error = false;
        while (idx >= 0)
        {
            var endIdx = text.IndexOf('>', idx + 5);
            if (endIdx < idx)
            {
                error = true;
                break;
            }
            endIdx++;
            text = text.Remove(idx, endIdx - idx);
            idx = text.IndexOf("<font", idx, StringComparison.OrdinalIgnoreCase);
        }
        if (!error)
        {
            text = text.Replace("</font>", ".");
        }

        foreach (var word in Utilities.RemoveSsaTags(text).Split(ExpectedChars, StringSplitOptions.RemoveEmptyEntries))
        {
            var s = word.Trim();
            if (s.Length > 1 && hashtable.ContainsKey(s))
            {
                hashtable[s]++;
            }
            else if (s.Length > 1)
            {
                hashtable.Add(s, 1);
            }
        }
    }

    private static void MostUsedLinesAdd(Dictionary<string, int> hashtable, string input)
    {
        var text = StripHtmlTags(input)
            .Replace('!', '.')
            .Replace('?', '.')
            .Replace("...", ".")
            .Replace("..", ".")
            .Replace('-', ' ')
            .FixExtraSpaces();

        text = Utilities.RemoveSsaTags(text);

        foreach (string line in text.Split('.'))
        {
            var s = line.Trim();
            if (hashtable.ContainsKey(s))
            {
                hashtable[s]++;
            }
            else if (s.Length > 0 && s.Contains(' '))
            {
                hashtable.Add(s, 1);
            }
        }
    }

    private static string StripHtmlTags(string input)
    {
        var text = input.Trim('\'').Replace("\"", string.Empty);

        if (text.Length < 8)
        {
            return text;
        }

        text = text.Replace("<i>", string.Empty);
        text = text.Replace("</i>", ".");
        text = text.Replace("<I>", string.Empty);
        text = text.Replace("</I>", ".");
        text = text.Replace("<b>", string.Empty);
        text = text.Replace("</b>", ".");
        text = text.Replace("<B>", string.Empty);
        text = text.Replace("</B>", ".");
        text = text.Replace("<u>", string.Empty);
        text = text.Replace("</u>", ".");
        text = text.Replace("<U>", string.Empty);
        text = text.Replace("</U>", ".");
        return text;
    }

    private void CalculateWordStatistics()
    {
        var hashtable = new Dictionary<string, int>(new StingOrdinalComparer());

        foreach (Paragraph p in _subtitle.Paragraphs)
        {
            MostUsedWordsAdd(hashtable, p.Text);
            _totalWords += p.Text.CountWords();
        }

        var sortedTable = new SortedDictionary<string, string>(new StingOrdinalComparer());
        foreach (KeyValuePair<string, int> item in hashtable)
        {
            if (item.Value > 1)
            {
                sortedTable.Add($"{item.Value:0000}" + "_" + item.Key, item.Value + ": " + item.Key);
            }
        }

        var sb = new StringBuilder();
        if (sortedTable.Count > 0)
        {
            var temp = string.Empty;
            foreach (KeyValuePair<string, string> item in sortedTable)
            {
                temp = item.Value + Environment.NewLine + temp;
            }
            sb.AppendLine(temp);
        }
        else
        {
            sb.AppendLine(_l.NothingFound);
        }

        TextMostUsedWords = sb.ToString();
    }

    private void CalculateMostUsedLines()
    {
        var hashtable = new Dictionary<string, int>();

        foreach (Paragraph p in _subtitle.Paragraphs)
        {
            MostUsedLinesAdd(hashtable, p.Text.Replace(Environment.NewLine, " ").Replace("  ", " "));
        }

        var sortedTable = new SortedDictionary<string, string>(new StingOrdinalComparer());
        foreach (KeyValuePair<string, int> item in hashtable)
        {
            if (item.Value > 1)
            {
                sortedTable.Add($"{item.Value:0000}" + "_" + item.Key, item.Value + ": " + item.Key);
            }
        }

        var sb = new StringBuilder();
        if (sortedTable.Count > 0)
        {
            var temp = string.Empty;
            foreach (KeyValuePair<string, string> item in sortedTable)
            {
                temp = item.Value + Environment.NewLine + temp;
            }
            sb.AppendLine(temp);
        }
        else
        {
            sb.AppendLine(_l.NothingFound);
        }

        TextMostUsedLines = sb.ToString();
    }

    internal void KeyDown(object? sender, KeyEventArgs e)
    {
        if (e.Key == Key.Escape)
        {
            Close();
        }
    }
}
