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

namespace BPASmartClient.MessageCommunication.MsgControl
{
    /// <summary>
    /// 内部消息总线
    /// </summary>
    public class InnerMessageBus
    {
        static InnerMessageBus _bus;
        const int TimeOut = 2000;
        static public InnerMessageBus Get_Instance()
        {
            if (_bus == null)
            {
                _bus = new InnerMessageBus();
            }
            return _bus;
        }

        #region 委托事件的定义
        /// <summary>
        /// 当触发引用事件时执行的委托
        /// </summary>
        public delegate void MessageEventHandler(object sender,InnerMessageEventArgs e);
        #endregion

        #region 自定义各类响应事件
        /// <summary>
        /// 返回为整数型的结果事件响应
        /// </summary>
        public event MessageEventHandler M_Event_消息事件;
        #endregion

        private readonly Object thisLock = new Object();

        /// <summary>
        /// 发送消息方法
        /// ----------------------------------------------
        /// </summary>
        /// <param name="sender">消息发送者</param>
        /// <param name="str_Msg">消息名称串</param>
        /// <param name="obj_Data">消息体数据区</param>
        public void PostMessage(object sender,string str_Msg,object obj_Data)
        {
            bool isLock = false;
            System.Threading.Monitor.TryEnter(thisLock,TimeOut,ref isLock);
            if (!isLock)//理论上不可能出现
            {
                return;
            }
            try
            {
                var temp = RouteTable.ToList();

                foreach (ListenPointInfo item in temp)
                {
                    if (MachMessageName(str_Msg,item))
                    {
                        InnerMessageEventArgs temp_arg = new InnerMessageEventArgs();
                        temp_arg.obj_Sender = sender;
                        temp_arg.obj_MessageObj = obj_Data;
                        temp_arg.str_MessageStr = str_Msg;
                        TypeHelper helper = new TypeHelper();
                        object[] args = new object[2];
                        args[0] = sender;
                        args[1] = temp_arg;

                        if (sender != null)
                        {
                            try
                            {
                                helper.M_Call_InstancMethod(item.PointObj,item.MethodName,args);
                            }
                            catch (Exception exp)
                            {

                            }
                        }
                    }
                }
            }
            catch (Exception exp)
            {
                //接收消息的调用方法发生异常
            }
            finally
            {
                System.Threading.Monitor.Exit(thisLock);
            }
        }

        /// <summary>
        /// 采用正则表达式匹配字符串
        /// </summary>
        /// <param name="MessageString"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        private static bool MachMessageName(string MessageString,ListenPointInfo item)
        {
            string value;
            string pattern;
            value = MessageString;
            try
            {
                pattern = item.str_Message.Replace("*",@"[-\.\w]*");
                ///使用正则表达式进行消息路由匹配;
                if (pattern.Contains('*'))
                {
                    if (Regex.IsMatch(value,pattern))
                    {
                        //Console.WriteLine("路由消息" + MessageString + " * " + (((item.PointObj.GetType()).FullName + "匹配成功！")));
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    if (value == pattern)
                    {
                        //Console.WriteLine("路由消息" + MessageString + "匹配成功！");
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("InnerMessageBus类MachMessageName方法出错，原因：" + ex.Message);

                return false;
            }
        }

        /// <summary>
        /// 消息路由表,内部的
        /// </summary>
        List<ListenPointInfo> RouteTable = new List<ListenPointInfo>();

        /// <summary>
        /// 外部应用调用消息
        /// </summary>
        /// <param name="obj_Listener">消息监听对象者</param>
        /// <param name="str_MessageString"></param>
        /// <param name="handler"></param>
        public void ListenMessage(object obj_Listener,string str_MessageString,string str_处理方法名称)
        {
            // arg = new InnerMessageEventArgs();
            Type[] argTypes = new Type[2];
            argTypes[0] = typeof(object);
            argTypes[1] = typeof(InnerMessageEventArgs);

            if (obj_Listener.GetType().GetMethod(str_处理方法名称,argTypes) != null)
            {
                ListenPointInfo info = new ListenPointInfo();
                info.PointObj = obj_Listener;
                info.str_Message = str_MessageString;
                info.MethodName = str_处理方法名称;
                bool isLock = false;
                System.Threading.Monitor.TryEnter(thisLock,TimeOut,ref isLock);
                if (!isLock)//理论上不可能出现
                {
                    return;
                }
                try
                {
                    RouteTable.Add(info);
                }
                finally
                {
                    System.Threading.Monitor.Exit(thisLock);
                }

            }
            else
            {
                TypeHelper helper = new TypeHelper();
                if ((helper.M_GetMethodInfosByName(obj_Listener.GetType(),str_处理方法名称).Count != 1))
                {
                    //taoye modified
                    Console.WriteLine("在使用消息中间件时,希望执行ListenMessage方法,绑定" + obj_Listener.GetType().ToString() + "中方法:" + str_处理方法名称 + ",但该方法不唯一或不存在.");
                }
            }

        }

        /// <summary>
        /// 关闭消息监听和事件的挂接关系
        /// </summary>
        /// <param name="str">消息名称</param>
        /// <param name="str_消息处理方法名称">消息处理方法名称</param>
        public void ListenMessage_trunOff(string str,string str_消息处理方法名称)
        {
            bool isLock = false;
            System.Threading.Monitor.TryEnter(thisLock,TimeOut,ref isLock);
            if (!isLock)//理论上不可能出现
            {
                return;
            }
            try
            {
                for (int i = RouteTable.Count - 1; i >= 0; i--)
                {
                    if (str == RouteTable[i].str_Message && str_消息处理方法名称 == RouteTable[i].MethodName)
                    {
                        RouteTable.RemoveAt(i);
                        break;
                    }
                }
            }
            finally
            {
                System.Threading.Monitor.Exit(thisLock);
            }
        }

        /// <summary>
        /// 采用对象方式直接释放指定对象的监听信息
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool RemoveRouteTableByObject(object obj)
        {
            bool isLock = false;
            System.Threading.Monitor.TryEnter(thisLock,TimeOut,ref isLock);
            if (!isLock)//理论上不可能出现
            {
                return false;
            }
            bool result = false;
            int currentI = -1;
            try
            {
                for (int i = 0; i < this.RouteTable.Count; i++)
                {
                    if (RouteTable[i].PointObj == obj)
                    {
                        currentI = i;
                    }
                }

                if (currentI != -1)
                {
                    RouteTable.RemoveAt(currentI);
                    result = true;
                }
            }
            finally
            {
                System.Threading.Monitor.Exit(thisLock);
            }
            return result;
        }

        /// <summary>
        /// 调试用属性,获取当前路由表所有的信息,只读
        /// </summary>
        public List<ListenPointInfo> __Debug_RoutTable
        {
            get
            {
                return this.RouteTable;
            }
        }
    }
}
