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 ActionManagerment
    {

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

        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();


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


        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 });
                    }
                }
            }

        }


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

        //}

        //public void Register(Action<object> action, string name)
        //{
        //    lock (RegisterLock)
        //    {
        //        if (action != null)
        //        {
        //            if (!actions.ContainsKey(name))
        //            {
        //                actions.TryAdd(name, new Delegation() { ActionObj = action });
        //            }
        //        }
        //    }
        //}

        //public void Register(Func<object> action, string name)
        //{
        //    lock (RegisterLock)
        //    {
        //        if (action != null)
        //        {
        //            if (!actions.ContainsKey(name))
        //            {
        //                actions.TryAdd(name, new Delegation() { FuncObj = action });
        //            }
        //        }
        //    }

        //}

        //public void Register(Func<object, object> action, string name)
        //{
        //    lock (RegisterLock)
        //    {
        //        if (action != null)
        //        {
        //            if (!actions.ContainsKey(name))
        //            {
        //                actions.TryAdd(name, new Delegation() { FuncPar = action });
        //            }
        //        }
        //    }
        //}

    }


    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; }
    }


}
