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;
using BPASmartClient.Message;

namespace BPASmartClient.Helper
{
    /// <summary>
    /// 线程管理
    /// </summary>
    public class ThreadManage : Singleton<ThreadManage>
    {
        string guid = "871d7e28-c413-4675-8d28-64e4dca4c2d3-";
        private static readonly object _lock = new object();
        StringBuilder callbackKey = new StringBuilder();
        List<string> keys = new List<string>();
        ConcurrentDictionary<string, Task> Threads = new ConcurrentDictionary<string, Task>();
        ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSources = new ConcurrentDictionary<string, CancellationTokenSource>();

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

        /// <summary>
        /// 长任务，带 while true 的循环
        /// </summary>
        /// <param name="action"></param>
        /// <param name="key"></param>
        public void StartLong(Action action, string key, bool IsRestart = false, Action RunComplete = null)
        {
            CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
            bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
             {
                 Thread.CurrentThread.Name = key;
             ReStart:
                 try
                 {
                     while (!CancellationTokenSources[guid + key].IsCancellationRequested)
                     {
                         if (action != null) action();
                     }
                 }
                 catch (Exception ex)
                 {
                     MessageLog.GetInstance.ShowEx(ex.ToString());
                     if (IsRestart)
                     {
                         Thread.Sleep(2000);
                         MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常，已重启");
                         goto ReStart;
                     }
                     else
                     {
                         CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource temp);
                         Threads.TryRemove(guid + key, out Task temp1);
                         MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常，已退出");
                     }
                 }
             }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
             {
                 ThreadStatus(t, o.ToString());
                 if (RunComplete != null) RunComplete();
             }), guid + key));
            MessageLog.GetInstance.Show($"启动线程 【{key}】");
            if (!result) MessageLog.GetInstance.Show($"【{key}】任务已存在，请检查 TaskName");

        }


        /// <summary>
        /// 不带 while true 的循环任务
        /// </summary>
        /// <param name="action"></param>
        /// <param name="key"></param>
        public void Start(Action action, string key, bool isRestart = false)
        {
            CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
            bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
            {
                Thread.CurrentThread.Name = key;
                try
                {
                    if (action != null) action();
                }
                catch (Exception ex)
                {
                    MessageLog.GetInstance.ShowEx(ex.ToString());
                    if (isRestart)
                    {
                        MessageLog.GetInstance.Show($"线程 【{key}】正在重启");
                        CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource item1);
                        Threads.TryRemove(guid + key, out Task item2);
                        Start(action, key, isRestart);
                    }
                    else
                    {
                        MessageLog.GetInstance.Show($"线程 【{key}】运行发生异常");
                    }
                }
            }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action<Task, object>((t, o) =>
             {
                 ThreadStatus(t, o.ToString());
             }), guid + key));
            MessageLog.GetInstance.Show($"启动线程 【{key}】");
            if (!result) MessageLog.GetInstance.Show($"【{key}】任务已存在，请检查 TaskName");
        }

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

            if (IsRemove)
            {
                if (Threads.ContainsKey(key))
                    Threads.TryRemove(key, out Task t);
                //Threads.TryRemove(Threads.FirstOrDefault(p => p.Key == TaskName));


                if (CancellationTokenSources.ContainsKey(key))
                    CancellationTokenSources.TryRemove(key, out CancellationTokenSource cts);
                //CancellationTokenSources.TryRemove(CancellationTokenSources.FirstOrDefault(p => p.Key == TaskName));
                //keys.Remove(key);
                //if (keys != null && keys.Count == 0) ActionManage.GetInstance.Send(callbackKey.ToString());
                ActionManage.GetInstance.Send(key);
            }
        }

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

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

    }

}
