using System;
using System.Linq;
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading.Tasks;
using Aitex.Core.Util;

namespace Aitex.Core.RT.OperationCenter
{
    public class OperationManager : ICommonOperation
    {
        ConcurrentDictionary<string, Func<string, object[], bool>> _keyValueMap;
        Func<object, bool> _isSubscriptionAttribute;
        Func<MemberInfo, bool> _hasSubscriptionAttribute;

        public OperationManager()
        {

        }

        public void Initialize()
        {
            _keyValueMap = new ConcurrentDictionary<string, Func<string, object[], bool>>();
            _isSubscriptionAttribute = attribute => attribute is SubscriptionAttribute;
            _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute);

            OP.InnerOperationManager = this;
        }

        public void Subscribe<T>(T instance, string keyPrefix = null) where T : class
        {
            if (instance == null)
                throw new ArgumentNullException("instance");

            Traverse(instance, keyPrefix);
        }

        public void Subscribe(string key, Func<string, object[], bool> op)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException("key");
            if (_keyValueMap.ContainsKey(key))
                throw new Exception(string.Format("Duplicated Key:{0}", key));
            if (op == null)
                throw new ArgumentNullException("op");

            _keyValueMap[key] = op;
        }

        public bool DoOperation(string operation, params object[] args)
        {
            if (!_keyValueMap.ContainsKey(operation))
            {
                throw new ApplicationException("调用了未发布的接口" + operation);
            }

            _keyValueMap[operation](operation, args);

            return true;
        }

        public void Traverse(object instance, string keyPrefix)
        {
            Parallel.ForEach(instance.GetType().GetMethods().Where<MethodInfo>(_hasSubscriptionAttribute), fi =>
            {
                string key = Parse(fi);
                key = string.IsNullOrWhiteSpace(keyPrefix) ? key : string.Format("{0}.{1}", keyPrefix, key);
                //Subscribe(key, fi.Invoke(instance, );
            });
        }

        string Parse(MethodInfo member)
        {
            return _hasSubscriptionAttribute(member) ? (member.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute).Key : null;
        }

        public void Record(string chamberId, string operation)
        {

        }

    }
}