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

namespace HBLConsole.Service
{
    public class ActionOperate
    {

        private volatile static ActionOperate _Instance;
        public static ActionOperate GetInstance => _Instance ?? (_Instance = new ActionOperate());
        private ActionOperate() { }

        private static ConcurrentDictionary<string, Delegation> actions = new ConcurrentDictionary<string, Delegation>();

        //private static ConcurrentDictionary<string, ActionManagerment> actionManagers = new ConcurrentDictionary<string, ActionManagerment>();

        static readonly object SendLock = new object();
        static readonly object SendParLock = new object();
        static readonly object RegisterLock = new object();

        /// <summary>
        /// 注销委托
        /// </summary>
        /// <param name="name"></param>
        public void CancelRegister(string name)
        {
            if (actions.ContainsKey(name))
            {
                actions.TryRemove(name, out Delegation t);
            }
        }

        public void Send(string name, object token, Action action = null)
        {
            lock (SendParLock)
                if (actions.ContainsKey(name))
                    if (actions[name].ActionObj != null)
                    {
                        actions[name].ActionObj(token);
                        if (action != null) action();
                    }
        }

        public void Send(string name, AsyncCallback action = null)
        {
            lock (SendLock)
                if (actions.ContainsKey(name))
                    if (actions[name].ActionBus != null)
                    {
                        if (action != null)
                            actions[name].ActionBus.BeginInvoke(action, null);
                        else
                            actions[name].ActionBus();
                    }

        }

        public object SendResult(string name, object token = null)
        {
            object result = new object();
            lock (SendParLock)
                if (actions.ContainsKey(name))
                    if (token == null)
                    {
                        if (actions[name].FuncObj != null)
                            result = actions[name].FuncObj;
                    }
                    else
                    {
                        if (actions[name].FuncPar != null)
                            result = actions[name].FuncPar(token);
                    }
            return result;
        }

        public void Register<T>(T action, string name)
        {
            lock (RegisterLock)
            {
                if (action != null)
                {
                    if (!actions.ContainsKey(name))
                    {
                        if (action is Action actionBus)
                            actions.TryAdd(name, new Delegation() { ActionBus = actionBus });

                        if (action is Action<object> actionObj)
                            actions.TryAdd(name, new Delegation() { ActionObj = actionObj });

                        if (action is Func<object> funcObj)
                            actions.TryAdd(name, new Delegation() { FuncObj = funcObj });

                        if (action is Func<object, object> puncPar)
                            actions.TryAdd(name, new Delegation() { FuncPar = puncPar });
                    }
                }
            }

        }

    }


    internal class Delegation
    {
        public Action<object> ActionObj { get; set; }

        public Action ActionBus { get; set; }
        public Action CallBack { get; set; }
        public Func<object> FuncObj { get; set; }
        public Func<object, object> FuncPar { get; set; }
    }


}
