using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.ServiceProcess;
using SuperWebSocket;
using System.Runtime.InteropServices;
using System.Text;

namespace JKZLICCardService

{
    public partial class MyWebSocketService : ServiceBase
    {

        public MyWebSocketService()
        {
            InitializeComponent();

        }

        WebSocketServer server;
        protected override void OnStart(string[] args)
        {
            var ip = ConfigurationManager.AppSettings["APWebSocketIP"];
            var port = ConfigurationManager.AppSettings["APWebSocketPort"];
            //WebSocket服务器端启动
            server = new WebSocketServer();
            if (!server.Setup(int.Parse(port)))
            {
                //Debug.Write("WebSocket服务器端启动失败");
                //处理启动失败消息
                return;
            }

            //新的会话连接时
            server.NewSessionConnected += server_NewSessionConnected;
            //会话关闭
            server.SessionClosed += server_SessionClosed;
            //接收到新的消息时
            server.NewMessageReceived += server_NewMessageReceived;

            if (!server.Start())
            {
                //Debug.Write(string.Format("开启WebSocket服务侦听失败:{0}:{1}", server.Config.Ip, server.Config.Port));
                //处理监听失败消息
                return;
            }
        }
        [DllImport("fzyktclient.dll", EntryPoint = "ykt_opendevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        protected static extern int ykt_opendevice(int nDeviceType, int nCom, int nBaud, IntPtr pRegion, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pWarnmsg, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pErrmsg);

        [DllImport("fzyktclient.dll", EntryPoint = "ykt_readopencardno_local", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        protected static extern int ykt_readopencardno_local(IntPtr pRegion, IntPtr pDeptid, IntPtr pDeptKey, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pCardtype, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pCardno, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pWarnmsg, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pErrmsg);

        [DllImport("fzyktclient.dll", EntryPoint = "ykt_readopencardinfo_local", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        protected static extern int ykt_readopencardinfo_local(IntPtr pRegion, IntPtr pDeptid, IntPtr pDeptKey,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pIssuedeptid,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pIssuedate,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pCardtype,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pCardno,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pIdtype,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pId,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pName,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pSex,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pBirthDate,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pCompany,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pAddress,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pTelephone,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pWarnmsg,
            [MarshalAs(UnmanagedType.LPStr)] StringBuilder pErrmsg);

        [DllImport("fzyktclient.dll", EntryPoint = "ykt_closedevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        protected static extern int ykt_closedevice([MarshalAs(UnmanagedType.LPStr)] StringBuilder pWarnmsg, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pErrmsg);



        protected override void OnStop()
        {
        }

        string KSessionId="";
        string VSessionId="";
        Dictionary<string, List<string>> msgDictionary = new Dictionary<string, List<string>>();
        private void server_NewMessageReceived(WebSocketSession session, string value)
        {
            log("接收到新的消息："+ value + "  来自："+ session.RemoteEndPoint + "  时间:"+ DateTime.Now);
            //收集在线session然后发送消息
            //var sessions = CommunicationServer.WebSocketServer.GetAllSessions();
            //foreach (WebSocketSession session in sessions)
            //{
            //    session.Send(DateTime.Now.ToString(Config.DateTimeFormat) + string.Format(format, arg));
            //}
            StringBuilder pCardtype = new StringBuilder(2);
            StringBuilder pCardno = new StringBuilder(40);
            StringBuilder pIssuedeptid = new StringBuilder(24);
            StringBuilder pIssuedate = new StringBuilder(8);
            StringBuilder pIdtype = new StringBuilder(2);
            StringBuilder pId = new StringBuilder(80);
            StringBuilder pName = new StringBuilder(40);
            StringBuilder pSex = new StringBuilder(1);
            StringBuilder pBirthDate = new StringBuilder(20);
            StringBuilder pCompany = new StringBuilder(70);
            StringBuilder pAddress = new StringBuilder(80);
            StringBuilder pTelephone = new StringBuilder(80);
            StringBuilder pWarnmsg = new StringBuilder(1024);
            StringBuilder pErrmsg = new StringBuilder(1024);

            if (value.Equals("readcardno"))
            {

                try
                {
                    int pval = ykt_opendevice(10, 9, 3, Marshal.StringToHGlobalAnsi("3502"), pWarnmsg, pErrmsg);

                    if (pval == 0)
                    {
                        log("打开成功");
                    }
                    else
                    {

                        log(string.Format("打开失败：{0}", pErrmsg.ToString()));
                    }
                }
                catch (Exception e)
                {
                    log(e.Message);
                    log(e.StackTrace);
                }

                try
                {
                    KSessionId = session.SessionID;
                    int pval = ykt_readopencardinfo_local(
                                Marshal.StringToHGlobalAnsi("3502"),
                                Marshal.StringToHGlobalAnsi("0303"),
                                Marshal.StringToHGlobalAnsi("123"),
                                pIssuedeptid,
                                pIssuedate,
                                pCardtype,
                                pCardno,
                                pIdtype,
                                pId,
                                pName,
                                pSex,
                                pBirthDate,
                                pCompany,
                                pAddress,
                                pTelephone,
                                pWarnmsg,
                                pErrmsg);
                    if (pval == 0)
                    {
                        log(string.Format("cardno:{0},name:{1},idcard{2}", pCardno, pName, pId));

                        SendMsgToRemotePoint(KSessionId, string.Format("cardno:{0},name:{1},idcard{2}", pCardno, pName, pId));
                    }
                    else
                    {
                        log("ykt_readopencardno_local:" + pErrmsg.ToString());
                    }
                }
                catch (Exception e)
                {
                    log(e.Message);
                    log(e.StackTrace);
                }

                try
                {
                    int pva3 = ykt_closedevice(pWarnmsg, pErrmsg);
                    if (pva3 != 0)
                    {
                        log("关闭设备失败:" + pErrmsg.ToString());

                    }
                }
                catch (Exception e)
                {
                    log(e.Message);
                    log(e.StackTrace);
                }

            }



        }

        /// <summary>
        /// 添加会话消息
        /// </summary>
        /// <param name="value"></param>
        private void AddMsgToSessionId(string value)
        {
            if (value != null)
            {
                //消息列表包含页面会话ID
                if (msgDictionary.ContainsKey(value))
                {
                    msgDictionary[value].Add(value);
                }
                //消息列表不包含页面会话ID
                else
                    msgDictionary.Add(value, new List<string>() { value });
            }
        }

        /// <summary>
        /// 会话关闭
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        private void server_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value)
        {
            log("会话关闭，关闭原因："+ value + "  来自："+ session.RemoteEndPoint + "  时间:"+ DateTime.Now);
            if (session.SessionID == KSessionId)
                SendMsgToRemotePoint(VSessionId, "已断开");
            else if (session.SessionID == VSessionId)
                SendMsgToRemotePoint(KSessionId, VSessionId + "已断开");
        }

        /// <summary>
        /// 新的会话链接
        /// </summary>
        /// <param name="session"></param>
        private void server_NewSessionConnected(WebSocketSession session)
        {
            log("新的会话连接  来自："+ session.RemoteEndPoint + " SessionID:"+ session.SessionID + "  时间:"+ DateTime.Now);
            //判断是否键存在，如果存在则锁定该键，赋值
            if (msgDictionary.ContainsKey(session.SessionID))
                msgDictionary[session.SessionID].ForEach(item => session.Send(item));
        }

        /// <summary>
        /// 发送消息到
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="msg"></param>
        private void SendMsgToRemotePoint(string sessionId, string msg)
        {
            var allSession = server.GetAppSessionByID(sessionId);
            if (allSession != null)
                allSession.Send(msg);
        }

        private void log(string msg){
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(System.IO.Directory.GetCurrentDirectory()+"//iccard_log.log", true))
            {
                file.WriteLine(msg);

            }
        }
    }
}
