using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace QuickMsg
{
    /// <summary>
    /// 消息服务器
    /// </summary>
    public class CustomMsg
    {
        readonly IntPtr handle;
        /// <summary>
        /// 消息事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void MsgEventHandler(object sender, MsgArgs e);
        /// <summary>
        /// 大小改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="Width"></param>
        /// <param name="Height"></param>
        public delegate void SizeEventHandler(object sender, int Width,int Height);
        /// <summary>
        /// 即将关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="cancel"></param>
        public delegate void ClosingEventHandler(object sender, bool cancel);
        private delegate IntPtr WndProcDelegate(IntPtr hwnd, int Msg, IntPtr wParam, IntPtr lParam);
        private readonly WndProcDelegate wndProcDelegate;
        [DllImport("User32.dll", CharSet= CharSet.Auto, SetLastError= true)]
		private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, WndProcDelegate wndProcDelegate);
        private readonly IntPtr oldWndFunc;
        /// <summary>
        /// 当收到消息时激发
        /// </summary>
        public event MsgEventHandler OnMsg;
        /// <summary>
        /// 消息处理类
        /// </summary>
        /// <param name="_form"></param>
        public CustomMsg(Form _form)
        {
            handle = _form.Handle;
            wndProcDelegate = new WndProcDelegate(WndProc);
            oldWndFunc = SetWindowLong(handle, MyDb.RyWin32.GWL_WNDPROC, wndProcDelegate);
            //System.Windows.Forms.Application.AddMessageFilter(this);
        }
        /// <summary>
        /// 
        /// </summary>
        ~CustomMsg()
        {
            WinAPI.User32.SetWindowLong(handle, MyDb.RyWin32.GWL_WNDPROC, oldWndFunc);
            //System.Windows.Forms.Application.RemoveMessageFilter(this);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        protected virtual void WndProc(ref System.Windows.Forms.Message msg)
        {
            DefWndProc(ref msg);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="m"></param>
        public void DefWndProc(ref System.Windows.Forms.Message m)
        {
            m.Result = WinAPI.User32.CallWindowProc(oldWndFunc, m.HWnd, m.Msg, m.WParam, m.LParam);
            if (m.Msg == MyDb.RyWin32.WM_COPYDATA)
            {
                var msg = MyDb.RyWin32.GetMsg(m, out IntPtr handle);
                MsgArgs msg_args2 = new MsgArgs
                {
                    From_handle = handle,
                    WParam = m.WParam.ToInt32(),
                    Msg_text = msg
                };
                Thread th = new Thread(delegate(){ Start(msg_args2); });
                th.Start();
                void Start(MsgArgs msg_args)
                {
                    OnMsg?.Invoke(this, msg_args);
                    if (msg_args.Reply_Text != "")
                    {
                        Send(handle, msg_args.WParam, msg_args.Reply_Text);
                    } 
                }
            }           
        }
        private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)
        {
            System.Windows.Forms.Message m = System.Windows.Forms.Message.Create(hWnd, msg, wParam, lParam);
            WndProc(ref m);
            return m.Result;
        }
        /// <summary>
        /// 发送消息,采用单线程发送
        /// </summary>
        /// <param name="to_handle">要发送到的句柄</param>
        /// <param name="wParam">编号</param>
        /// <param name="msg">消息内容</param>
        public int Send2(IntPtr to_handle,int wParam, string msg)
        {
           return MyDb.RyWin32.SendMsg(handle, to_handle, wParam, msg);
        }
        /// <summary>
        /// 发送消息，采用多线程发送
        /// </summary>
        /// <param name="to_handle">要发送到的句柄</param>
        /// <param name="wParam">编号</param>
        /// <param name="msg">消息内容</param>
        public void Send(IntPtr to_handle, int wParam, string msg)
        {
            Thread th = new Thread(delegate () {
                MyDb.RyWin32.SendMsg(handle, to_handle, wParam, msg);
            });
            th.Start();
        }
    }
    /// <summary>
    /// 消息类
    /// </summary>
    public class MsgArgs
    {
        /// <summary>
        /// 是否取消
        /// </summary>
        public bool Cancel { get; internal set; } = false;
        /// <summary>
        /// 来源句柄
        /// </summary>
        public IntPtr From_handle { get; internal set; } = IntPtr.Zero;
        /// <summary>
        /// 
        /// </summary>
        public int WParam {get;  set;} = 0;
        /// <summary>
        /// 消息文本
        /// </summary>
        public string Msg_text { get; internal set; } = "";
        /// <summary>
        /// 需要回复的内容
        /// </summary>
        public string Reply_Text { get; set; } = "";
    }
}
