using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;

namespace HBLConsole.Service
{
    /// <summary>
    /// 线程管理
    /// </summary>
    public class ThreadOperate
    {
        private volatile static ThreadOperate _Instance;
        public static ThreadOperate GetInstance => _Instance ?? (_Instance = new ThreadOperate());
        private ThreadOperate() { }

        ConcurrentDictionary<string, Task> Threads = new ConcurrentDictionary<string, Task>();
        ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSources = new ConcurrentDictionary<string, CancellationTokenSource>();

        /// <summary>
        /// 停止指定任务
        /// </summary>
        /// <param name="taskName">任务名</param>
        /// <param name="ExitCallback">任务结束的回调</param>
        public void StopTask(string taskName, Action ExitCallback = null)
        {
            if (CancellationTokenSources.ContainsKey(taskName))
                CancellationTokenSources[taskName]?.Cancel();
            ActionOperate.GetInstance.Register(ExitCallback, taskName);
        }

        /// <summary>
        /// 长任务，带 while true 的循环
        /// </summary>
        /// <param name="action"></param>
        /// <param name="TaskName"></param>
        public void StartLong(Action action, string TaskName, Action RunComplete = null)
        {
            CancellationTokenSources.TryAdd(TaskName, new CancellationTokenSource());
            bool result = Threads.TryAdd(TaskName, Task.Factory.StartNew(new Action(() =>
            {
                while (!CancellationTokenSources[TaskName].IsCancellationRequested)
                {
                    if (action != null) action();
                }
            }), CancellationTokenSources[TaskName].Token).ContinueWith(new Action<Task, object>((t, o) =>
            {
                ThreadStatus(t, o.ToString());
                if (RunComplete != null) RunComplete();
            }), TaskName));
            MessageLog.GetInstance.Show($"启动线程 【{TaskName}】");
            if (!result) MessageLog.GetInstance.Show($"【{TaskName}】任务已存在，请检查 TaskName");

        }


        /// <summary>
        /// 不带 while true 的循环任务
        /// </summary>
        /// <param name="action"></param>
        /// <param name="TaskName"></param>
        public void Start(Action action, string TaskName)
        {
            CancellationTokenSources.TryAdd(TaskName, new CancellationTokenSource());
            bool result = Threads.TryAdd(TaskName, Task.Factory.StartNew(new Action(() =>
            {
                action();
            }), CancellationTokenSources[TaskName].Token).ContinueWith(new Action<Task, object>((t, o) =>
             {
                 ThreadStatus(t, o.ToString());
             }), TaskName));
            if (!result) MessageLog.GetInstance.Show($"【{TaskName}】任务已存在，请检查 TaskName");
        }

        private void ThreadStatus(Task task, string TaskName)
        {
            bool IsRemove = false;
            switch (task.Status)
            {
                case TaskStatus.RanToCompletion:
                    MessageLog.GetInstance.Show($"线程【{TaskName}】执行完成");
                    IsRemove = true;
                    break;
                case TaskStatus.Faulted:
                    MessageLog.GetInstance.Show($"线程【{TaskName}】执行异常，{task.Exception}");
                    IsRemove = true;
                    break;
                case TaskStatus.Canceled:
                    MessageLog.GetInstance.Show($"线程【{TaskName}】已取消");
                    IsRemove = true;
                    break;
                default:
                    break;
            }

            if (IsRemove)
            {
                Threads.TryRemove(Threads.FirstOrDefault(p => p.Key == TaskName.ToString()));

                CancellationTokenSources.TryRemove(CancellationTokenSources.FirstOrDefault(p => p.Key == TaskName.ToString()));

                ActionOperate.GetInstance.Send(TaskName);
            }
        }

        /// <summary>
        /// 释放所有线程资源
        /// </summary>
        public void Dispose()
        {
            for (int i = 0; i < CancellationTokenSources.Count; i++)
            {
                CancellationTokenSources.ElementAt(i).Value.Cancel();
            }
        }

        /// <summary>
        /// 判断指定线程是否完成
        /// </summary>
        /// <param name="TaskName"></param>
        /// <returns></returns>
        public bool IsComplete(string TaskName)
        {
            if (Threads.ContainsKey(TaskName))
            {
                return Threads[TaskName].IsCompleted;
            }
            else
            {
                return false;
            }
        }

    }

}
