using JLHHJSvr.LJException;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace JLHHJSvr.Tools
{
    public class IntervalScheduledTask
    {
        public string Name { get; }
        public TimeSpan Interval { get; }
        public Action TaskAction { get; }
        private readonly object _syncRoot = new object();
        private Timer _timer;
        private bool _running;

        public IntervalScheduledTask(string name, TimeSpan interval, Action action)
        {
            if (interval <= TimeSpan.Zero) throw new LJCommonException("间隔时间必须大于0");
            Name = name;
            Interval = interval;
            TaskAction = action;
            _timer = new Timer(_ => Execute(), null, interval, interval);
        }

        private void Execute()
        {
            lock (_syncRoot)
            {
                if (_running) return;
                _running = true;
            }

            try
            {
                Trace.Write($"{Name}间隔任务执行!!!");
                TaskAction.Invoke();
            }
            catch (Exception ex)
            {
                Trace.Write(ex);
            }
            finally
            {
                lock (_syncRoot)
                {
                    _running = false;
                }
            }
        }

        public void Stop() => _timer?.Dispose();
    }

    public class IntervalSchedulerManager
    {
        private readonly Dictionary<string, IntervalScheduledTask> _tasks = new Dictionary<string, IntervalScheduledTask>();

        public void AddTask(string name, TimeSpan interval, Action action)
        {
            if (_tasks.ContainsKey(name)) throw new LJCommonException($"任务 \"{name}\" 已存在");
            _tasks[name] = new IntervalScheduledTask(name, interval, action);
        }

        public void RemoveTask(string name)
        {
            if (_tasks.TryGetValue(name, out var task))
            {
                task.Stop();
                _tasks.Remove(name);
            }
        }

        public void StopAll()
        {
            foreach (var task in _tasks.Values) task.Stop();
            _tasks.Clear();
        }
    }
}
