using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter19.Listing19_17.Tests
{
    using System.Text.RegularExpressions;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class ProgramTests
    {

        string TargetNamespaceName { get { return typeof(Program).Namespace; } }

        [TestMethod]
        public void AsyncVoidReturnTest()
        {
            string expected = $@"Wywołanie Task.Run...(ID wątku: *)
Wykonywanie zadania... (ID wątku: *)
Powiadomienie w metodzie Post...(ID wątku: *)
Powiadomienie w metodzie Post...(ID wątku: *)
Zgłaszanie oczekiwanego wyjątku....(ID wątku: *)
System.Exception: Expected Exception
   *(ID wątku: *)";

            string output = IntelliTect.TestTools.Console.ConsoleAssert.ExpectLike(expected,
            () =>
            {
                Program.Main();
            });

            Console.WriteLine(output);

            // Weryfikowanie, że tylko identyfikator wątku z punktu 'Wykonywanie zadania...' 
            // (drugi wiersz) jest unikatowy.
            MatchCollection matches = Regex.Matches(output, @"\(ID wątku: (\d)+\)");
            int firstThreadId = int.Parse(matches[0].Groups[1].Value);
            int secondThreadId = int.Parse(matches[1].Groups[1].Value);
            int? expectedThreadId;
            for (int i = 0; i < matches.Count; i++)
            {
                switch (i)
                {
                    case 0:
                    case 4:
                    case 5:
                        expectedThreadId = firstThreadId;
                        break;
                    case 1:
                        // Oczywiste.
                        expectedThreadId = secondThreadId;
                        break;
                    default:
                        // Nieznany.
                        expectedThreadId = null;
                        break;
                }
                if (expectedThreadId != null)
                {
                    Assert.AreEqual<int?>(expectedThreadId, int.Parse(matches[i].Groups[1].Value),
                        $"Dopasowanie {i} to '{matches[i].Groups[0].Value}'. Oczekiwano '{expectedThreadId}'");
                }
            }
            Assert.AreEqual<int>(6, matches.Count, "Mniej dopasowań id wątków niż oczekiwano.");
        }
    }
}
