﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace thread_modeler.ThreadModeler
{
    class RobinRoundManager : GenericThreadManager
    {
        private List<EmulatedThread> list; //my own queue
        private List<EmulatedThread> external_list; //my own list of threads
        private int Time;
        private EmulatedThread current = null;

        public RobinRoundManager()
        {
            external_list = this.threads.ToList();
            list = new List<EmulatedThread>();
            
        }

        public override void StartSimulation()
        {
            EmulatedThread thread = threads.First();
            Timer timer = new Timer(CPU_BURST_IN_MS);
            timer.Elapsed += timer_Elapsed;
            foreach (EmulatedThread em in this.threads)
            {
                list.Add(em);
            }
            Time = 0;
            timer.Start();
        }

        private EmulatedThread Next(EmulatedThread currentThread, List<EmulatedThread> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i] == currentThread)
                {
                    int nexti;
                    if (i == list.Count - 1)
                    {
                        nexti = 0;
                    }
                    else
                        nexti = i + 1;
                    return list[nexti];
                }
            }
            return list[0];
        }

        private void timer_Elapsed(object source, ElapsedEventArgs e)
        {
            //add the new threads to queue with starttime = time
            IEnumerable<EmulatedThread> Threads = list.FindAll(thread => thread.StartTime == Time);
            foreach (EmulatedThread t in Threads)
            {
                external_list.Add(t);
            }
            if (external_list.Count == 0) 
            {
                Timer timer = (Timer)source;
                timer.Stop();
                return;
            }
            current = Next(current, external_list);

            if (current.CpuBurst > 0 && current.Thread.ThreadState == System.Threading.ThreadState.Unstarted)
            {
                current.Thread.Start();
                current.CpuBurst--;
                Console.WriteLine("Running thread #" + current.ThreadId);
            }
            else if (current.CpuBurst > 0 && current.Thread.ThreadState == System.Threading.ThreadState.Running)
            {
                current.CpuBurst--;
                Console.WriteLine("Running thread #" + current.ThreadId);
            }
            else
            {
                try
                {
                    current.Thread.Abort();
                }
                finally
                {
                    //Thread was closed succefully
                    Console.WriteLine("Destroying thread #" + current.ThreadId);
                }
                external_list.Remove(current);
            }
            Time++;
        }
    }
}
