using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    class Program
    {
        public static Dictionary<int, List<int>> Contacts = new Dictionary<int, List<int>>();
        public static HashSet<int> InfectedPeople = new HashSet<int>();

        static void Main(string[] args)
        {
            string path = $@"../../../forrasok/elek.txt";

            var data = File.ReadAllLines(path);

            foreach (var item in data)
            {
                string[] nums = item.Split(' ');
                int infector = Convert.ToInt32(nums[0]);
                int infected = Convert.ToInt32(nums[1]);

                if (Contacts.ContainsKey(infector))
                {
                    Contacts[infector].Add(infected);
                }
                else
                {
                    Contacts[infector] = new List<int> { infected };
                }
            }

            Virus rootVirus = new Virus(2);
            InfectedPeople.Clear(); // Clear the set before starting the spread
            InfectedPeople.Add(2); // Add the root virus to the infected set
            SpreadBFS(rootVirus, 2);
            //Spread(rootVirus, 9);

            //rootVirus.PrintInfectionTreeWithDepth(2, 0, "->");
            rootVirus.PrintInfectionTree();

            Console.WriteLine(InfectedPeople.Count);
        }


        public static void SpreadBFS(Virus rootVirus, int maxDepth)
        {
            Queue<(Virus virus, int depth)> queue = new Queue<(Virus virus, int depth)>();
            queue.Enqueue((rootVirus, 0));

            while (queue.Count > 0)
            {
                var (currentVirus, currentDepth) = queue.Dequeue();

                if (currentDepth >= maxDepth)
                {
                    continue;
                }

                if (Contacts.ContainsKey(currentVirus.Name))
                {
                    foreach (var contact in Contacts[currentVirus.Name])
                    {
                        if (!InfectedPeople.Contains(contact))
                        {
                            Virus newInfected = new Virus(contact, currentDepth + 1);
                            currentVirus.Infect(newInfected);
                            InfectedPeople.Add(contact); // Mark as infected
                            queue.Enqueue((newInfected, currentDepth + 1));
                        }
                    }
                }

                // Check if the current virus should be healed
                if (currentDepth - currentVirus.InfectionTurn >= 8)
                {
                    InfectedPeople.Remove(currentVirus.Name);
                }
            }
        }

        public static void Spread(Virus virus, int maxDepth, int currentDepth = 0)
        {
            if (currentDepth >= maxDepth)
            {
                return;
            }

            if (Contacts.ContainsKey(virus.Name))
            {
                foreach (var contact in Contacts[virus.Name])
                {
                    if (!InfectedPeople.Contains(contact))
                    {
                        Virus newInfected = new Virus(contact);
                        virus.Infect(newInfected);
                        InfectedPeople.Add(contact); // Mark as infected
                        Spread(newInfected, maxDepth, currentDepth + 1);
                    } else
                    {
                        Virus newInfected = new Virus(contact);
                        virus.Infect(newInfected);
                        //InfectedPeople.Add(contact); // Mark as infected
                        Spread(newInfected, maxDepth, currentDepth + 1);
                    }

                }
            }
        }

        /*
        public static void Spread(Virus virus)
        {
            if (Contacts.ContainsKey(virus.Name))
            {
                foreach (var contact in Contacts[virus.Name])
                {
                    if (!InfectedPeople.Contains(contact))
                    {
                        Virus newInfected = new Virus(contact);
                        virus.Infect(newInfected);
                        InfectedPeople.Add(contact); // Mark as infected
                        Spread(newInfected);
                    }
                }
            }
        }
        */

    }
}
