using System;
using System.Collections.Generic;
using System.Linq;

namespace OCR
{
    public static class Extensions
    {
        /// <summary>
        /// Removes duplicate words on corresponding places created by overlaping text boxes
        /// </summary>
        /// <param name="words">list of words</param>
        /// <returns>list of words without duplicate words</returns>
        public static List<Word> RemoveDuplicateWords(this List<Word> words)
        {
            var toBeRemoved = new List<Word>();
            foreach (var word in words) {
                var duplicateWords = words.Where(x => word.Position.BoundingRect.Contains(x.Position.Center)).ToList();
                if (duplicateWords.Count > 1)
                    toBeRemoved.AddRange(duplicateWords.OrderByDescending(x=>x.Position.Width).Skip(1));
            }
            foreach (var word in toBeRemoved) {
                Console.WriteLine($"Removing duplicate word: {word.PossibleWords.First().Word}");
                words.Remove(word);
            }
            return words;
        }


        /// <summary>
        /// Filters words, takes the word with highest probability if bigger than minimal probability threshold
        /// </summary>
        /// <param name="words">list of words to be filtered</param>
        /// <param name="threshold">minimal probability of word to be taken into account, default 0.9f</param>
        /// <returns>list of most probable words</returns>
        public static List<Word> FilterWords(this List<Word> words, float threshold = 0.9f)
        {
            foreach (var wordToFilter in words) {
                wordToFilter.PossibleWords = new List<PossibleWord> { wordToFilter.GetBestWord() };
            }
            var filteredWords = words.Where(x => x.PossibleWords.First().Probability > threshold).ToList();
            return filteredWords;
        }


        /// <summary>
        /// Prints the output of OCR
        /// </summary>
        /// <param name="evaluationResults">list of recognized words</param>
        public static void PrintOutput(this List<Word> evaluationResults)
        {
            Console.WriteLine(String.Concat(Enumerable.Repeat("=", 25)) + "  RECOGNITION  OUTPUT  " + String.Concat(Enumerable.Repeat("=", 25)));
            var tableHeader = new List<string>() { "TextBoxId", "WordInBoxId", "PossibleWord", "WordPosition" };
            Console.WriteLine("| {0} | {1} | {2} | {3} |", tableHeader[0], tableHeader[1], tableHeader[2].PadLeft(20), tableHeader[3].PadLeft(20));
            Console.WriteLine(String.Concat(Enumerable.Repeat("-", 73)));
            foreach (var evaluationResult in evaluationResults)
            {
                var boxPosition = "X: " + evaluationResult.Position.Center.X + " Y: " +
                                  evaluationResult.Position.Center.Y;
                Console.WriteLine("| {0} | {1} | {2} | {3} |", evaluationResult.TextBoxId.ToString().PadLeft(9), evaluationResult.WordInBoxId.ToString().PadLeft(11),
                    evaluationResult.PossibleWords.First().Word.PadLeft(20), boxPosition.PadLeft(20));
            }
            Console.WriteLine(String.Concat(Enumerable.Repeat("-", 73)));
        }
    }
}
