using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace QuickMsg
{
    /// <summary>
    /// 消息服务端类
    /// </summary>
    public class MsgMain
    {
        readonly CustomMsg MSG;
        /// <summary>
        /// 判断当前消息主服务器是否创建成功
        /// </summary>
        public bool IsOk
        {
            get;private set;
        }
        /// <summary>
        /// 当收到消息时激发
        /// </summary>
        public event CustomMsg.MsgEventHandler OnMsg;
        /// <summary>
        /// 当收到自定义消息时(非系统消息)激发
        /// </summary>
        public event CustomMsg.MsgEventHandler OnCustomMsg;
        /// <summary>
        /// 有消息客户端发起连接请求时激发
        /// </summary>
        public event CustomMsg.MsgEventHandler OnConnect;
        /// <summary>
        /// 有消息客户端连接成功时激发
        /// </summary>
        public event CustomMsg.MsgEventHandler OnConnected;
        /// <summary>
        /// 有消息客户端断开连接时激发
        /// </summary>
        public event CustomMsg.MsgEventHandler OnDisConnect;
      
        private readonly Form form=null;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id">服务端ID,需要唯一性,共客户端识别</param>
        /// <param name="_form">服务端</param>
        public MsgMain(string id,Form _form)
        {
            object mainHandle = RyMemoryShare.ReadFromMemory(1024, typeof(Int64), id);
            if (mainHandle == null)
            {
                RyMemoryShare.WriteToMemory(1024, _form.Handle.ToInt64(), id);
                form = _form;
                MSG = new CustomMsg(_form);//创建消息通道
                MSG.OnMsg += MSG_OnMsg;
                IsOk = true;
            }
            else { IsOk = false; }
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Free()
        {
            if(form!=null)
            {
               // RyMemoryShare.WriteToMemory(1024, form.Handle.ToInt64(), id);
            }
        }
        /// <summary>
        /// 判断是否包含指定客户端
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        public bool HaveClient(IntPtr handle)
        {
            bool isHave = false;
            for (int i = 0; i < Client_list.Count; i++)
            {
                if (Client_list[i].Handle == handle) { isHave = true; break; }
            }
            return isHave;
        }
        /// <summary>
        /// 
        /// </summary>
        public List<ClientItem> Client_list { get;private set; } = new List<ClientItem>();
       /// <summary>
       /// 设置客户端大小
       /// </summary>
        public void Resize(int width,int height)
        {
            ryCommon.Storage Stor = new ryCommon.Storage();
            Stor.SelectNodeBySet();
            Stor.SetAttrValue("op", "resize");
            Stor.SetAttrValue("width", width);
            Stor.SetAttrValue("height", height);
            SendAll(MyDb.RyWin32.Sys_chanel_id, "xml"+Stor.XMLText);
        }
        /// <summary>
        /// 根据客户端ID,获取客户端对象
        /// </summary>
        /// <param name="ClientId"></param>
        /// <returns></returns>
        public ClientItem GetClientItem(string ClientId)
        {
            for (int i = Client_list.Count - 1; i >= 0; i--)
            {
                if (Client_list[i].ClientId == ClientId)
                {
                    return Client_list[i];
                }
            }
            return null;
        }
        /// <summary>
        /// 根据客户端句柄,获取客户端对象
        /// </summary>
        /// <param name="Handle"></param>
        /// <returns></returns>
        public ClientItem GetClientItem(IntPtr Handle)
        {
            for (int i = Client_list.Count - 1; i >= 0; i--)
            {
                if (Client_list[i].Handle == Handle)
                {
                    return Client_list[i];
                }
            }
            return null;
        }
        /// <summary>
        /// 关闭所有客户端
        /// </summary>
        public void CloseClient()
        {
            SendAll(MyDb.RyWin32.Sys_chanel_id, "close");
            Client_list.Clear();
        }
       /// <summary>
       /// 关闭指定客户端
       /// </summary>
       /// <param name="handle"></param>
        public void CloseClient(IntPtr handle)
        {
            MSG.Send(handle, MyDb.RyWin32.Sys_chanel_id, "close");
        }
        /// <summary>
        /// 关闭指定客户端
        /// </summary>
        /// <param name="item"></param>
        public void CloseClient(ClientItem item)
        {
            MSG.Send(item.Handle, MyDb.RyWin32.Sys_chanel_id, "close");
            for (int i = Client_list.Count-1; i >=0; i--)
            {
               if(Client_list[i].Handle== item.Handle)
                {
                    Client_list.RemoveAt(i);
                }
            }
        }
        /// <summary>
        /// 向所有客户端发送消息，单线程
        /// </summary>
        /// <param name="wParam"></param>
        /// <param name="msg"></param>
        public void SendAll(int wParam, string msg)
        {
            for (int i = 0; i < Client_list.Count; i++)
            {
                MSG.Send2(Client_list[i].Handle, wParam, msg);//发送消息
            }
        }
        /// <summary>
        /// 向指定客户端发送消息
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="wParam"></param>
        /// <param name="msg"></param>
        public void Send(IntPtr handle, int wParam, string msg)
        {
            MSG.Send(handle, wParam, msg);//发送消息
        }
        /// <summary>
        /// 关闭在指定时间前失去响应的子客户端
        /// </summary>
        /// <param name="dt"></param>
        public void CloseLoseClient(DateTime dt)
        {
            for (int i = Client_list.Count - 1; i >= 0; i--)
            {
                if (Client_list[i].HeartTime<= dt)
                { Client_list.RemoveAt(i); }
            }
        }
        private void MSG_OnMsg(object sender, MsgArgs e)
        {
            OnMsg?.Invoke(this,e);
            if(e.WParam== MyDb.RyWin32.Sys_chanel_id) //如果是系统通道请求
            {
                switch(e.Msg_text)
                {
                    case "disconnect"://断开连接
                        #region 断开连接
                        for (int i = Client_list.Count - 1; i >= 0; i--)
                        {
                            if (Client_list[i].Handle == e.From_handle) { Client_list.RemoveAt(i); break; }
                        }
                        OnDisConnect?.Invoke(this, e);
                        break;
                    #endregion
                    case "heart"://心跳包
                        #region 更新心跳时间
                        MSG.Send(e.From_handle, MyDb.RyWin32.Sys_chanel_id,"heart");//回应给客户端
                        for (int i = Client_list.Count - 1; i >= 0; i--)
                        {
                            if (Client_list[i].Handle == e.From_handle)
                            { Client_list[i].HeartTime=DateTime.Now; break; }
                        }
                        break;
                    #endregion
                    default:
                        #region 如果是xml消息
                        if (e.Msg_text.StartsWith("xml"))
                        {
                            ryCommon.Storage Stor = new ryCommon.Storage(e.Msg_text.Substring(3));
                            Stor.SelectNodeBySet();
                            switch (Stor.GetAttrValue("op"))
                            {
                                case "connect"://连接请求
                                    #region 连接请求
                                    OnConnect?.Invoke(this, e);
                                    if (!e.Cancel)//如果允许连接
                                    {
                                        bool isHave = false;
                                        for (int i = 0; i < Client_list.Count; i++)
                                        {
                                            if (Client_list[i].Handle == e.From_handle) { Client_list[i].ConnectTime = DateTime.Now; isHave = true; break; }
                                        }
                                        if (!isHave)
                                        {
                                            Client_list.Add(new ClientItem() { Handle = e.From_handle, ClientId= Stor.GetAttrValue("clientid") });//加入到客户端列表里
                                        }
                                        MSG.Send(e.From_handle, e.WParam, "connected");//发送连接成功的通知
                                        OnConnected?.Invoke(this, e);
                                    }
                                    break;
                                    #endregion
                            }
                        }
                        break;
                        #endregion
                }
            }
            else
            {
                OnCustomMsg?.Invoke(this, e);
            }
        }
    }
    /// <summary>
    /// 客户端信息
    /// </summary>
    public class ClientItem
    {
        /// <summary>
        /// 客户端句柄
        /// </summary>
        public IntPtr Handle { get; set; } = IntPtr.Zero;
        /// <summary>
        /// 客户端ID
        /// </summary>
        public string ClientId { get; set; } ="";
        /// <summary>
        /// 客户端连接时间
        /// </summary>
        public DateTime ConnectTime { get; set; } = DateTime.Now;
        /// <summary>
        /// 心跳时间
        /// </summary>
        public DateTime HeartTime { get; set; } = DateTime.Now;

    }
}
