using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using BlackBoxFile;

namespace Dispatch
{
    /// <summary>
    /// 网络通信类
    /// </summary>
    public class CSNetComm
    {
        private static Thread gs_netThread;              // 网络线程
        private static bool gs_startFlag;                // 启动标志位
        private static bool gs_pauseFlag;                // 暂停标志位
        private static IPAddress gs_ipAddr;              // IP地址
        private static int gs_listenPort;                // 监听端口
        private static CSNetServer gs_server;
        private static List<CSNetConThread> gs_nctList;
        private static ManualResetEvent gs_resumeEvent;

        private static List<byte> gs_netBuffer;

        private static object netLock = new object();
        private static Thread threadNet;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void MatchedParityHandler(object sender, DataEventArgs e);
        /// <summary>
        /// 
        /// </summary>
        public static event MatchedParityHandler MatchedParity;
        private static void OnMatchedParity(object sender, DataEventArgs e)
        {
            if (MatchedParity != null)
            {
                MatchedParity(sender, e);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="o"></param>
        public static void OnMatchParity(object o)
        {
            MyNetData data = o as MyNetData;
            Console.ForegroundColor = ConsoleColor.Yellow;
            //Console.WriteLine("所在线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString() + "类型:" + data.e.type + "  " + CHex2String.Byte2HexString(data.e.data, data.e.data.Length));
            Console.ResetColor();
            OnMatchedParity(data.sender, data.e);
            Thread.Sleep(500);//加延时是为了避免解析后有过长的操作占用系统资源
        }
        private class MyNetData
        {
            /// <summary>
            /// 对象
            /// </summary>
            public object sender;
            /// <summary>
            /// 事务
            /// </summary>
            public DataEventArgs e;
        }
        /// <summary>
        /// 
        /// </summary>
        public CSNetComm()
        {
            gs_startFlag = false;
            gs_pauseFlag = false;
            gs_ipAddr = IPAddress.Parse("127.0.0.1");
            gs_listenPort = 8899;
            gs_nctList = new List<CSNetConThread>();
            gs_resumeEvent = new ManualResetEvent(false);
            gs_netBuffer = new List<byte>();

            threadNet = new Thread(ThreadHandler);
            threadNet.Start();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="ipAddr"></param>
        /// <param name="listenPort"></param>
        public static void Init(IPAddress ipAddr, int listenPort)
        {
            gs_ipAddr = ipAddr;
            gs_listenPort = listenPort;
            gs_server = new CSNetServer(gs_ipAddr, gs_listenPort);
        }

        /// <summary>
        /// 发送字节数据
        /// </summary>
        /// <param name="n">连接线程ID</param>
        /// <param name="buffer">数据缓冲区</param>
        /// <param name="length">数据长度</param>
        public static void SendBytes(int n, byte[] buffer, int length)
        {
            //foreach (CSNetConThread nct in gs_nctList)
            for (int i = 0; i < gs_nctList.Count; i++)
            {
                CSNetConThread nct = gs_nctList[i];
                nct.SendBytes(buffer, length);
            }
        }
        /// <summary>
        /// 获取线程挂起状态
        /// </summary>
        /// <returns></returns>
        public static bool GetPauseStatus()
        {
            return gs_pauseFlag;
        }

        /// <summary>
        /// 获取服务器开启状态
        /// </summary>
        /// <returns></returns>
        public static bool GetStartStatus()
        {
            return gs_startFlag;
        }

        /// <summary>
        /// 线程暂停
        /// </summary>
        public static void Pause()
        {
            gs_resumeEvent.Reset();
            gs_pauseFlag = true;
        }
        /// <summary>
        /// 线程恢复
        /// </summary>
        public static void Resume()
        {
            gs_resumeEvent.Set();
            gs_pauseFlag = true;
        }

        /// <summary>
        /// 启动
        /// </summary>
        public static void Start(string ipAddr, int listenPort)
        {
            gs_ipAddr = IPAddress.Parse(ipAddr);
            gs_listenPort = listenPort;
            // 开启网络监听线程
           gs_netThread = new Thread(new ThreadStart(ThreadProc));
           gs_netThread.Start();
        }

        /// <summary>
        /// 停止
        /// </summary>
        public static void Stop()
        {
            if (!gs_startFlag)
            {
                return;
            }

            gs_startFlag = false;

            while (CSNetConThread.GetConnectedNum() != 0)
            {
                Thread.Sleep(10);
            }

            gs_server.Stop();
            gs_netThread.Abort();
        }

        /// <summary>
        /// 添加网络连接线程实例
        /// </summary>
        /// <param name="nct">网络连接线程实例</param>
        public static void AddNetConThread(CSNetConThread nct)
        {
            gs_nctList.Add(nct);
        }
        /// <summary>
        /// 删除网络连接线程实例
        /// </summary>
        /// <param name="nct">网络连接线程实例</param>
        public static void RemoveNetConThread(CSNetConThread nct)
        {
            gs_nctList.Remove(nct);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="n"></param>
        public void RemoveNetThread(int n)
        {
            bool flag = false;
            CSNetConThread delnct = new CSNetConThread();
            foreach (CSNetConThread nct in gs_nctList)
            {
                if (n == nct.GetID())
                {
                    flag = true;
                    delnct = nct;
                    break;
                }
            }
            if (flag)
            {
                CSNetConThread.gs_connectedNum--;
                delnct.CloseClient();
                RemoveNetConThread(delnct);
            }
        }

        /// <summary>
        /// 线程过程
        /// </summary>
        private static void ThreadProc()
        {
            gs_server = new CSNetServer(gs_ipAddr, gs_listenPort);

            gs_startFlag = gs_server.Start();

            if (!gs_startFlag)
            {
                return;
            }

            while (true)
            {
                // 如果线程已被挂起
                if (gs_pauseFlag)
                {
                    //gs_resumeEvent.WaitOne();
                }
                while (!gs_server.Pending())
                {
                    Thread.Sleep(1000); // 延时1秒
                }

                /************************************************************************/
                /* 利用线程池技术开启新连接                                                                     */
                /************************************************************************/
                CSNetConThread newConThread = new CSNetConThread();
                newConThread.SetListener(gs_server.GetListener());
                //ThreadPool.QueueUserWorkItem(new WaitCallback(newConThread.ThreadProc));
                Thread thread = new Thread(new ThreadStart(newConThread.ThreadProc));
                thread.Start();
                Pause();
            }
        }

        /// <summary>
        /// 批量追加网络数据缓存 
        /// </summary>
        /// <param name="buffer">数据缓存</param>
        /// <param name="length">数据长度</param>
        public static void AddNetBufferRange(byte[] buffer, int length)
        {
            for (int i = 0; i < length; i++)
            {
                gs_netBuffer.Add(buffer[i]);
            }
        }

        private static byte[] DataHander(out int type)
        {
            type = -1;
            int framelength = 14;           // 帧长度
            byte frameHead = 0x10;          // 帧头
            byte frameTaig = 0x03;
            byte frameFunc1 = 0x41;
            byte frameFunc2 = 0x42;
            byte frameFunc3 = 0x53;
            byte frameFunc4 = 0x54;

            if (gs_netBuffer.Count >= framelength)
            {
                #region MyRegion
                if ((gs_netBuffer[0] == frameHead) && (gs_netBuffer[2] == frameFunc1 || gs_netBuffer[2] == frameFunc2
                    || gs_netBuffer[2] == frameFunc3 || gs_netBuffer[2] == frameFunc4) && (gs_netBuffer[13] == frameTaig))
                {
                    byte checkSum = 0x00;
                    for (int i = 0; i < 12; i++)
                    {
                        checkSum ^= gs_netBuffer[i];
                    }
                    if (checkSum == gs_netBuffer[12])
                    {
                        byte[] data = new byte[14];
                        for (int i = 0; i < 14; i++)
                        {
                            data[i] = gs_netBuffer[i];
                        }
                        lock (netLock)
                        {
                            gs_netBuffer.RemoveRange(0, 14);
                        }
                        type = 2;
                        return data;
                    }
                    else
                    {
                        ArrangeBuffer(gs_netBuffer, frameHead);
                    }
                }
                else if ((gs_netBuffer[0] == frameHead) && (gs_netBuffer.Count >= 10) && gs_netBuffer[1] == 0x62)//轮询的解析
                {
                    byte checkSum = 0x00;
                    for (int i = 0; i < 8; i++)
                    {
                        checkSum ^= gs_netBuffer[i];
                    }
                    if (checkSum == gs_netBuffer[8] && frameTaig == gs_netBuffer[9])
                    {
                        byte[] data = new byte[10];
                        for (int i = 0; i < 10; i++)
                        {
                            data[i] = gs_netBuffer[i];
                        }
                        lock (netLock)
                        {
                            gs_netBuffer.RemoveRange(0, 10);
                        }
                        type = 2;
                        return data;
                    }
                    else
                    {
                        ArrangeBuffer(gs_netBuffer, frameHead);
                    }
                }
                else
                {
                    ArrangeBuffer(gs_netBuffer, frameHead);
                }
                #endregion
            }
            return new byte[1] { 0 };
        }
        static AutoResetEvent done = new AutoResetEvent(true);//在处理数据的时候不允许被打断（只有在线程正常挂起时有效）
        /// <summary>
        /// 
        /// </summary>
        public void ThreadHandler()
        {
            while (true)
            {
                //Console.WriteLine("分析线程运行中...");
                if (gs_netBuffer.Count > 0)
                {
                    done.Reset();
                    byte[] buffer;
                    int type;
                    buffer = DataHander(out type);
                    DataEventArgs e = new DataEventArgs();
                    e.type = type;
                    e.data = buffer;
                    if (type != -1)
                    {
                        MyNetData data = new MyNetData();
                        data.sender = this;
                        data.e = e;
                        Thread t = new Thread(OnMatchParity);
                        t.Start(data);
                    }
                }
                Thread.Sleep(20);
                done.Set();
            }
        }
        /// <summary>
        /// 整理数据缓存表
        /// </summary>
        /// <param name="bufferList">数据缓存表</param>
        /// <param name="targetByte">目标字节</param>
        private static void ArrangeBuffer(List<byte> bufferList, byte targetByte)
        {
            int delBytes = 1;

            for (int i = 1; i < bufferList.Count; i++)
            {
                if (bufferList[i] == targetByte)
                {
                    break;
                }
                else
                {
                    delBytes++;
                }
            }

            try
            {
                lock (netLock)
                {
                    bufferList.RemoveRange(0, delBytes);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 网路连接线程类
        /// </summary>
        public class CSNetConThread
        {
            /// <summary>
            /// 已建立连接数
            /// </summary>
            public static int gs_connectedNum = 0;     // 
            private const int gc_bufferSize = 1024;    // 缓冲区的大小
            private static List<byte> gs_netBuffer;    // 网络数据缓存
            /// <summary>
            /// TCP联接
            /// </summary>
            public TcpClient tcpclient;

            private TcpListener listener;
            private int id;
            private int rxBytes;
            private int txBytes;
            private byte[] rxBuffer;
            private byte[] txBuffer;
            //private bool readFlag;
            private bool writeFlag;

            /// <summary>
            /// 默认构造
            /// </summary>
            public CSNetConThread()
            {
                id = 0;
                rxBytes = 0;
                txBytes = 0;
                //readFlag = false;
                writeFlag = false;
                rxBuffer = new byte[gc_bufferSize];
                txBuffer = new byte[gc_bufferSize];
                gs_netBuffer = new List<byte>();
                tcpclient = new TcpClient();
            }

            /// <summary>
            /// 获取连接线程ID
            /// </summary>
            /// <returns>连接线程ID</returns>
            public int GetID()
            {
                return this.id;
            }

            private int GenerateID()
            {
                int id = 0;
                id = gs_connectedNum;
                return id;
            }
            /// <summary>
            /// 关闭所有联接
            /// </summary>
            public void CloseClient()
            {
                IPEndPoint iep = (IPEndPoint)tcpclient.Client.RemoteEndPoint;
                tcpclient.Close();
            }
            /// <summary>
            /// 获取联接数量
            /// </summary>
            /// <returns></returns>
            public static int GetConnectedNum()
            {
                return gs_connectedNum;
            }
            /// <summary>
            /// 设置监听器
            /// </summary>
            /// <param name="tl">TCP监听器</param>
            public void SetListener(TcpListener tl)
            {
                this.listener = tl;
            }
            /// <summary>
            /// 发送字节数组
            /// </summary>
            /// <param name="buffer"></param>
            /// <param name="length"></param>
            public void SendBytes(byte[] buffer, int length)
            {
                while (writeFlag)
                {
                    Thread.Sleep(10);
                }

                txBuffer = buffer;
                txBytes = length;

                writeFlag = true;
            }

            /// <summary>
            /// 线程执行过程
            /// </summary>
            public void ThreadProc()//object state
            {
                bool acceptFlag = true;
                TcpClient client = new TcpClient();

                try
                {
                    client = listener.AcceptTcpClient();
                }
                catch (SocketException ex)
                {
                    string str = "";
                    string strDateInfo = "出现的异常：" + DateTime.Now.ToString() + "\r\n";

                    if (ex != null)
                    {
                        str = string.Format(strDateInfo + "异常类型：{0}\r\n异常消息：{1}\r\n异常信息：{2}\r\n",
                        ex.GetType().Name, ex.Message, ex.StackTrace);
                    }
                    else
                    {
                        str = string.Format("应用程序线程错误:{0}", ex);
                    }
                    Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, str);
                    //Program.writeLog(str);
                    // 此处需要发送异常消息
                    acceptFlag = false;
                }
                tcpclient = client;
                IPEndPoint iep1 = (IPEndPoint)tcpclient.Client.RemoteEndPoint;
                //////////////////////////////////////////////////
                gs_connectedNum++;
                ////////////////////////////////////////////////////
                //this.id = GenerateID();

                CSNetComm.AddNetConThread(this);

                // 等待网络通信监听线程挂起，然后恢复该线程运行
                //while (!CSNetComm.GetPauseStatus())
                //{}
                CSNetComm.Resume();

                #region 连接成功
                if (acceptFlag)
                {
                    NetworkStream ns = client.GetStream();

                    // 发送已连接事件
                    IPEndPoint iep = (IPEndPoint)client.Client.RemoteEndPoint;
                    string ipStr = iep.Address.ToString();
                    string portStr = "[" + iep.Port.ToString() + "]";
                    string msgText = "Client" + this.id.ToString() + "\t\t" + ipStr + "\t" + portStr;
                    //SendMessage(MessgeType.EVENT_CLIENT_CONNECTED, msgText, 0, 0);

                    //发送欢迎语
                    //string welcomeStr = "Welcome to CASUN CMS Server!";
                    //rxBuffer = Encoding.ASCII.GetBytes(welcomeStr);
                    //ns.Write(rxBuffer, 0, rxBuffer.Length);

                    /************************************************************************/
                    /* 数据发送操作                                                          */
                    /************************************************************************/
                    #region
                    while (true)
                    {
                        // 查询通信监听服务器是否打开
                        if (!CSNetComm.GetStartStatus())
                        {
                            break;
                        }
                        if (client.Connected == false)
                        {
                            break;
                        }
                        // 检测当前套接字1ms是否为可读
                        if (client.Client.Poll(1000, SelectMode.SelectRead))
                        {
                            try
                            {
                                rxBytes = ns.Read(rxBuffer, 0, rxBuffer.Length);
                            }
                            catch (System.Exception ex)
                            {
                                Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
                            }
                            if (rxBytes > 0)
                            {
                                this.id = rxBuffer[2];
                            }
                            //如果连接已关闭
                            if (rxBytes == 0)
                            {
                                msgText = "Client" + this.id.ToString() + "\t\t" + ipStr + "\t" + portStr;
                                //SendMessage(MessgeType.EVENT_CLIENT_DISCONNECTED, msgText, 0, 0);
                                break;
                            }
                            else
                            {
                                string str = null;
                                for (int i = 0; i < rxBytes; i++)
                                    str += Convert.ToString(rxBuffer[i], 16).ToString() + " ";
                                //writeLog1(DateTime.Now.ToString() + str);

                                CSNetComm.AddNetBufferRange(rxBuffer, rxBytes);
                                //发送工作数据接收消息
                                //SendMessage(MessgeType.EVENT_WORK_DATA_RECEIVED, "", recvNum, this.id);
                            }
                        }
                        if (client.Connected == false)
                        {
                            break;
                        }
                        // 检测当前套接字1ms内是否为可写
                        if (client.Client.Poll(1000, SelectMode.SelectWrite))
                        {
                            if (writeFlag)
                            {
                                try
                                {
                                    ns.Write(txBuffer, 0, txBytes);
                                }
                                catch (Exception ex)
                                {
                                    Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
                                }
                                writeFlag = false;
                                Encoding e = Encoding.GetEncoding(936);
                                msgText = e.GetString(txBuffer, 0, txBytes);
                                //SendMessage(MessgeType.EVENT_DATA_SENDED, msgText, sendNum, this.id);
                            }
                        }
                    }// end of while
                    #endregion
                    ns.Close();
                }// end of if ( acceptFlag )
                #endregion

                // 接入线程执行完毕需要的相关操作
                client.Close();
                gs_connectedNum--;
                CSNetComm.RemoveNetConThread(this);
            }
        }
    }

    /// <summary>
    /// 网络服务器类
    /// </summary>
    internal class CSNetServer
    {
        // 成员变量
        private TcpListener listener;

        // 成员函数
        /// <summary>
        /// 默认构造
        /// </summary>
        public CSNetServer()
        {
            string ipStr = "127.0.0.1";
            int port = 9808;

            this.listener = new TcpListener(IPAddress.Parse(ipStr), port);
        }

        /// <summary>
        /// 重载构造
        /// </summary>
        /// <param name="addr">地址</param>
        /// <param name="port">端口</param>
        public CSNetServer(IPAddress addr, int port)
        {
            this.listener = new TcpListener(addr, port);
        }

        public bool Pending()
        {
            try
            {
                return listener.Pending();
            }
            catch (System.Exception ex)
            {
                //需要向控制线程传递ex.Message
                Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
                return false;
            }
        }

        public bool Start()
        {
            try
            {
                listener.Start();
            }
            catch (System.Exception ex)
            {
                //需要向控制线程传递ex.Message
                Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
                return false;
            }

            return true;
        }

        public bool Stop()
        {
            try
            {
                listener.Stop();
            }
            catch (System.Exception ex)
            {
                //需要向控制线程传递ex.Message
                Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
                return false;
            }

            return true;
        }

        public TcpListener GetListener()
        {
            return (this.listener);
        }

        public void SetListener(IPAddress addr, int port)
        {
            //this.listener. ;
        }
    }

}

