using System;
using System.Collections.Generic;
using System.Threading;

namespace Quadarax.Foundation.Core.Thread
{
    public class MoshPit<TContext> where TContext : class
    {
        private readonly List<Action<TContext>> _actions;
        private Timer? _timer;
        private readonly Random _random;


        public TContext Context { get; set; }

        public long Iterations { get; private set; }
        public TimeSpan AvgIterationDuration { get; private set; }
        public TimeSpan TotalDuration { get; private set; }
        public decimal AvgIterationPerSecond { get; private set; }
        public MoshPit(TContext context)
        {
            Context = context;
            _actions = new List<Action<TContext>>();
            _random = new Random();
        }

        public void AddAction(Action<TContext> action)
        {
            _actions.Add(action);
        }

        public void Start(int iterationInterval, int totalDuration)
        {
            _timer = new Timer(ExecuteRandomAction, Context, 0, iterationInterval);

            // Stop the _timer after the specified duration
            _ = new Timer((e) => _timer.Dispose(), null, totalDuration, Timeout.Infinite);

            System.Threading.Thread.Sleep(totalDuration);
        }

        private void ExecuteRandomAction(object? state)
        {
            if (state == null)
                throw new ArgumentNullException(nameof(state));

            var context = (TContext)state;

            if (_actions.Count > 0)
            {
                Iterations++;
                var index = _random.Next(_actions.Count);
                var startIteration = DateTime.Now;

                _actions[index](context);
                
                var durationIteration = DateTime.Now - startIteration;
                TotalDuration = TotalDuration.Add(durationIteration);
                AvgIterationDuration = TimeSpan.FromTicks(TotalDuration.Ticks / Iterations);
                if (AvgIterationDuration==TimeSpan.Zero)
                    AvgIterationPerSecond = 0;
                else
                    AvgIterationPerSecond = TimeSpan.FromSeconds(1).Ticks / (decimal)AvgIterationDuration.Ticks;
            }
        }
    }
}
