using System;
using System.Collections.Concurrent;

namespace XGame.Framework.ThreadScheduler
{
    /// <summary>
    /// 线程调度
    /// </summary>
    public static class ThreadSchedulers
    {
        private class TaskInfo
        {
            public Action<object> Action;
            public object Context;

            public void Clear()
            {
                Action = null;
                Context = null;
            }
        }
        private static ConcurrentQueue<TaskInfo> _queueTasks = new ConcurrentQueue<TaskInfo>();
        private static ConcurrentQueue<TaskInfo> _taskPool = new ConcurrentQueue<TaskInfo>();


        public static void RunOnMainThread(Action<object> action, object context)
        {
            var task = Get();
            task.Action = action;
            task.Context = context;
            _queueTasks.Enqueue(task);
        }

        private static void Recycle(TaskInfo task)
        {
            if (task != null)
            {
                task.Clear();
                _taskPool.Enqueue(task);
            }
        }

        private static TaskInfo Get()
        {
            if (!_taskPool.TryDequeue(out TaskInfo task))
                task = new TaskInfo();
            return task;
        }

        public static void Update()
        {
            while (_queueTasks.TryDequeue(out TaskInfo task))
            {
                if (task != default)
                {
                    try
                    {
                        task.Action.Invoke(task.Context);
                    }
                    catch (Exception e)
                    {
                        if (e.InnerException != null)
                        {
                            Log.Error($"[ThreadSchedulers] Message: {e.InnerException.Message},\n" +
                                      $"StackTrace: {e.InnerException.StackTrace}");
                        }
                        else
                        {
                            Log.Error($"[ThreadSchedulers] Message: {e.Message} \n" +
                                      $"StackTrace: {e.StackTrace}");
                        }
                    }
                    finally
                    {
                        Recycle(task);
                    }
                }
            }
        }

        public static void Dispose()
        {
            while (_queueTasks.TryDequeue(out var task)) ;
            while (_taskPool.TryDequeue(out var task)) ;
        }
    }
}