using System;
using System.Collections;
//using System.Threading.Tasks;
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Mesnac.DeviceAdapter.Fuchs
{

    public enum RecvState
    {
        //Pepperl_Fuchs 返回数据 00.06.0A.02.FF.49.
        //00.14.0A.02.00.4A.30.00.30.05.FB.63.AC.1F.36.81.EC.88.04.68

        WaitingBeginChar1_State = 1,         //等待接收帧同步字符1 0x00
        WaitingBeginChar2_State = 2,         //等待接收帧同步字符2 0x06
        WaitingBeginChar3_State = 3,         //等待接收帧同步字符3 0x01
        WaitingBeginChar4_State = 4,         //等待接收帧同步字符4 0x02
        WaitingBeginChar5_State = 5,         //等待接收帧同步字符5 0xFF
        WaitingBeginChar6_State = 6,         //等待接收帧同步字符6 0x49
        WaitingForChar7_State = 7,           //等待接收帧同步字符7 0x00
    };

    class BgTcpClient : ICommunicateService
    {
        private Semaphore m_ReciveSem = new Semaphore(0, 100000);
        RecvState enumRecvState = RecvState.WaitingBeginChar1_State;
        int m_iPosition = 0;
        byte[] m_szFullMessage = new byte[1024];  //此数组用于状态机
        int iBarcodeLength = 0;//条码长度

        FuchsAdapter m_FuchsAdapter = null;

        private BackgroundWorker m_bgwReceive = new BackgroundWorker();
        private BackgroundWorker m_bgwDeal = new BackgroundWorker();
        private string m_FsIP = "";
        private Int32 m_FnPort = 0;

        private Socket m_ClientSock = null;

        private ArrayList m_FrecvData = new ArrayList();
        private Semaphore m_Fsem = new Semaphore(0, 100000);
        private ManualResetEvent Exitevent = new ManualResetEvent(false);
        public AntInfo[] AntList = AntListInfo.AntList;
        public event RecvIdentifyData RecvIdentifyDataEvent = null;
        //接收线程
        private void bgwReceive_DoWork(object sender, DoWorkEventArgs e)
        {
            int nPackLen = 1024;
            byte[] buff = new byte[nPackLen];
            while (true)
            {
                try
                {
                    if (m_ClientSock != null && m_ClientSock.Connected)
                    {
                        int nCount = m_ClientSock.Receive(buff, nPackLen, 0);
                        if (nCount > 0)
                        {
                            //if(buff[0] != 0X00 && buff[1] != 0X06 && buff[2] != 0X00)
                            //{
                            //LogService.Instance.Info("方法：bgwReceive_DoWork，Pepperl_Fuchs接收原始报文:" + bytesToHexStr(buff, nCount));
                            //}
                            if (buff[4] == 0XFF)
                            {
                                Array.Clear(buff, 0, nCount);
                            }
                            else
                            {
                                m_FuchsAdapter.LogInfo.Info("方法：bgwReceive_DoWork，Pepperl_Fuchs设备：" + m_FsIP + ":" + m_FnPort + "接收原始报文:" + bytesToHexStr(buff, nCount));
                                PareReceiveData(buff, nCount); //调用状态机函数
                            }
                            //ThreadPool.QueueUserWorkItem(new WaitCallback(PareSend_ReceiveData),buff);
                            continue;
                        }
                        else                   //接收错误
                        {
                            if (m_ClientSock != null)
                            {
                                m_ClientSock.Close();
                                m_ClientSock = null;
                            }
                            e.Cancel = true;
                            m_Fsem.Release();
                        }
                    }
                    else
                    {
                        e.Cancel = true;
                        if (m_ClientSock != null)
                        {
                            m_ClientSock.Close();
                            m_ClientSock = null;
                        }
                        m_Fsem.Release();
                        return;
                    }
                    Thread.Sleep(10);
                }
                catch (Exception ex)
                {
                    e.Cancel = true;
                    if (m_ClientSock != null)
                    {
                        m_ClientSock.Close();
                        m_ClientSock = null;
                    }
                    m_FuchsAdapter.LogInfo.Info("Socket接收数据线程退出" + ex.ToString());
                    m_Fsem.Release();
                    return;
                }
                if (this.m_bgwReceive.CancellationPending)
                {
                    e.Cancel = true;
                    if (m_ClientSock != null)
                    {
                        m_ClientSock.Close();
                        m_ClientSock = null;
                    }
                    m_Fsem.Release();
                    return;
                }
            }
        }

        private void PareSend_ReceiveData(object ReceiveData)
        {
            byte[] buffer = (byte[])ReceiveData;
            if (buffer[3] == 0X32)  //高频连续识别返回自报数据接收
            {
                if (m_FuchsAdapter != null)
                {
                    m_FuchsAdapter.LogInfo.Info("方法：PareSend_ReceiveData，线程池1号天线发送停止指令");
                    m_FuchsAdapter.Device_StopIdentify(1); //处理函数
                }
            }
            else if (buffer[3] == 0X34)
            {
                if (m_FuchsAdapter != null)
                {
                    m_FuchsAdapter.LogInfo.Info("方法：PareSend_ReceiveData，线程池2号天线发送停止指令");
                    m_FuchsAdapter.Device_StopIdentify(2); //处理函数
                }
            }
            else if (buffer[3] == 0X36)
            {
                if (m_FuchsAdapter != null)
                {
                    m_FuchsAdapter.LogInfo.Info("方法：PareSend_ReceiveData，线程池3号天线发送停止指令");
                    m_FuchsAdapter.Device_StopIdentify(3); //处理函数
                }
            }
            else if (buffer[3] == 0X38)
            {
                if (m_FuchsAdapter != null)
                {
                    m_FuchsAdapter.LogInfo.Info("方法：PareSend_ReceiveData，线程池4号天线发送停止指令");
                    m_FuchsAdapter.Device_StopIdentify(4); //处理函数
                }
            }
        }

        //发送线程（包括接收后的处理）
        private void bgwDeal_DoWork(object sender, DoWorkEventArgs e)
        {
            //LogService.Instance.Info("Pepperl_Fuchs 进入 bgwDeal_DoWork 线程：");
            while (true)
            {
                try
                {
                    m_Fsem.WaitOne();
                    //m_ReciveSem.WaitOne();
                    lock (m_FrecvData)
                    {
                        if (m_FrecvData.Count > 0)
                        {
                            byte[] buff = (byte[])m_FrecvData[0];
                            if (m_FuchsAdapter != null)
                            {
                                m_FuchsAdapter.Device_DealValidPack(buff); //处理函数
                            }
                            m_FrecvData.RemoveAt(0);
                        }
                    }
                    if (Exitevent.WaitOne(0, false))
                    {
                        e.Cancel = true;
                        m_FuchsAdapter.LogInfo.Info("Socket处理数据线程正常退出");
                        Exitevent.Reset();
                        return;
                    }
                    Thread.Sleep(10);
                }
                catch (Exception ex)
                {
                    e.Cancel = true;
                    m_FuchsAdapter.LogInfo.Info("Socket处理数据异常： " + ex.ToString());
                    return;
                }
                if (this.m_bgwDeal.CancellationPending)
                {
                    m_FuchsAdapter.LogInfo.Info("Socket处理数据线程异常退出");
                    e.Cancel = true;
                    return;
                }
            }
        }

        //发送函数
        public bool SendMessage(MessagePack pMessagePack)
        {
            UInt16 iPos = 0;
            byte[] u16byte = new byte[2];
            try
            {
                byte[] SendBuffer = new byte[pMessagePack.m_pData.Length];   //起始字符1

                //SendBuffer[iPos] = pMessagePack.m_BeginChar;
                //iPos += 1;

                //SendBuffer[iPos] = pMessagePack.m_SecondChar;          //起始字符2
                //iPos += 1;

                //SendBuffer[iPos] = pMessagePack.m_pData[pMessagePack.m_pData.Length];       //起始字符3
                //iPos += Convert.ToUInt16(pMessagePack.m_pData.Length);

                //SendBuffer[iPos] = pMessagePack.m_Channel;   //通道号
                Array.Copy(pMessagePack.m_pData, 0, SendBuffer, iPos, pMessagePack.m_pData.Length);   //数据域
                //if (pMessagePack.m_pData[0] != 0X00 && pMessagePack.m_pData[1] != 0X16 && pMessagePack.m_pData[2] != 0X0A)//过滤日志中的心跳报文
                //{
                m_FuchsAdapter.LogInfo.Info("方法：SendMessage，Pepperl_Fuchs设备：" + m_FsIP + ":" + m_FnPort + "发送原始报文:" + bytesToHexStr(SendBuffer, pMessagePack.m_pData.Length));
                //}
                int nCount = m_ClientSock.Send(SendBuffer, pMessagePack.m_pData.Length, SocketFlags.None);
                if (nCount > 0)   //发送成功
                {
                    //LogService.Instance.Info("m_ClientSock.Send函数发送成功");
                    return true;
                }
                else
                {
                    m_FuchsAdapter.LogInfo.Info("方法：SendMessage，连接已断开，数据发送失败");
                    return false;
                }
            }
            catch (Exception ex)
            {
                m_FuchsAdapter.LogInfo.Info("方法：SendMessage，Pepperl_Fuchs设备：" + m_FsIP + ":" + m_FnPort + "发送报文失败，请检查网络连接！");
                return false;
            }
        }

        #region 初始化一套函数
        public bool Connect()
        {
            //连接       
            try
            {
                Exitevent.Reset();
                if (m_FsIP == "" || m_FnPort == 0)
                {
                    m_FuchsAdapter.LogInfo.Info("IP和端口号不能为空，连接失败");
                    return false;
                }
                if (m_ClientSock != null && GetState())
                {
                    //LogService.Instance.Info("已经连接了");
                    return true;
                }
                m_ClientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint iep = new IPEndPoint(IPAddress.Parse(m_FsIP), m_FnPort);
                m_ClientSock.Connect(iep);
                if (m_ClientSock.Connected)
                {
                    try
                    {
                        //启动接收线程  

                        m_bgwReceive.DoWork += new DoWorkEventHandler(bgwReceive_DoWork);
                        m_bgwReceive.RunWorkerAsync();
                        //启动处理线程
                        m_bgwDeal.DoWork += new DoWorkEventHandler(bgwDeal_DoWork);
                        m_bgwDeal.RunWorkerAsync();
                        return true;
                    }
                    catch (Exception ex)
                    {
                        m_FuchsAdapter.LogInfo.Info("创建后台线程异常 " + ex.ToString());
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                m_FuchsAdapter.LogInfo.Info("IP:" + m_FsIP + "，端口号：" + m_FnPort + "，Socket连接异常!");
                return false;
            }
        }

        public bool DisConnect()
        {
            try
            {
                Exitevent.Set();
                m_Fsem.Release();
                Thread.Sleep(100);
                //if (m_bgwReceive.IsBusy)
                //{
                //    m_bgwReceive.CancelAsync();
                //}
                //if (m_bgwDeal.IsBusy)
                //{
                //    m_bgwDeal.CancelAsync();
                //}
                if (m_ClientSock != null)
                {
                    m_ClientSock.Disconnect(false);
                    m_ClientSock.Close();
                    m_ClientSock = null;
                }
                return true;
            }
            catch (Exception ex)
            {
                m_FuchsAdapter.LogInfo.Info("Socket连接异常 " + ex.ToString());
                return false;
            }
        }

        public bool GetState()
        {
            bool bResult = false;
            bool blockingState = false;
            try
            {
                if (m_ClientSock != null)
                {
                    blockingState = m_ClientSock.Blocking;
                    byte[] tmp = new byte[1];

                    m_ClientSock.Blocking = false;
                    m_ClientSock.Send(tmp, 0, 0);
                    bResult = true;
                    Console.WriteLine("Connected!");
                }
                else
                {
                    bResult = false;
                }
            }
            catch (SocketException e)
            {
                // 10035 == WSAEWOULDBLOCK
                if (e.NativeErrorCode.Equals(10035))
                {
                    bResult = true;
                    Console.WriteLine("Still Connected, but the Send would block");
                }
                else
                {
                    bResult = false;
                    Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
                }
            }
            finally
            {
                if (m_ClientSock != null)
                {
                    m_ClientSock.Blocking = blockingState;
                }
            }

            return bResult;
        }

        public void Init(string strIp, int iPort, object objetcter)
        {
            Exitevent.Reset();
            m_FsIP = strIp;
            m_FnPort = iPort;
            m_FuchsAdapter = objetcter as FuchsAdapter;
        }
        #endregion

        //状态机函数
        public void PareReceiveData(byte[] buffer, int iLen)
        {
            Array.Clear(m_szFullMessage, 0, 1024);
            switch (buffer[2])
            {
                case 0X19:  //高频读头开始连续识别指令
                    Deal_BeginIdentify(buffer, iLen);
                    break;
                case 0X00: //心跳
                    Deal_HeartPack(buffer, iLen);
                    break;
                case 0X02://高频及超高频读头停止连续识别指令
                    Deal_StopIdentify(buffer, iLen);
                    break;
                case 0X71://超高频读头开始连续识别指令
                    Deal_UHFBeginIdentify(buffer, iLen);
                    break;
                case 0X0A:  //超高频读头单次读标签指令
                    Deal_UHFReadData(buffer, iLen);
                    break;
                case 0X10:  //高频读头单次读标签指令
                    Deal_HFReadData(buffer, iLen);
                    break;
                case 0X05://高频读头NoData
                    Deal_HFNoData(buffer, iLen);
                    break;
                case 0X04://设置读头工作模式高频or超高频
                    Deal_SetAntCT(buffer, iLen);
                    break;
                case 0X0D:
                    Deal_UHFWriteData(buffer, iLen);
                    break;
                case 0XBF:
                    Deal_UHFSetSignelModel(buffer, iLen);
                    break;
                default:
                    break;
            }
        }

        private void Deal_UHFSetSignelModel(byte[] buffer, int iLen)
        {
            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();
        }


        private void Deal_UHFWriteData(byte[] buffer, int iLen)
        {
            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();
        }

        private void Deal_SetAntCT(byte[] buffer, int iLen)
        {
            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();
        }

        private void Deal_HFNoData(byte[] buffer, int iLen)
        {
            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();
        }

        private void Deal_HFReadData(byte[] buffer, int iLen)
        {
            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();
        }

        private void Deal_UHFReadData(byte[] buffer, int iLen)
        {
            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();
        }

        public void deal_TagInfo(byte Ant)
        {
            AntList[Ant - 1].ReadData = null;
            while (AntList[Ant - 1].IsReading)
            {
                if (AntList[Ant - 1].ReadData != null)
                {
                    m_FuchsAdapter.Device_DealValidPack(AntList[Ant - 1].ReadData);
                    Array.Clear(AntList[Ant - 1].ReadData, 0, AntList[Ant - 1].ReadData.Length);
                    AntList[Ant - 1].IsReading = false;
                }
            }
        }

        public void Receive_tagInf(DateTime dt1, byte Ant, int timeout, bool TagInventory)
        {
            AntList[Ant - 1].ReadData = null;
            while (TagInventory)
            {
                int dt = (int)DateTime.Now.Subtract(dt1).TotalMilliseconds;
                if (AntList[Ant - 1].ReadData != null)
                {
                    m_FuchsAdapter.Device_DealValidPack(AntList[Ant - 1].ReadData);
                    Array.Clear(AntList[Ant - 1].ReadData, 0, AntList[Ant - 1].ReadData.Length);
                    TagInventory = false;
                }
                if (dt > timeout)
                {
                    //m_FuchsAdapter.DealNoData(Ant);
                    if (!m_FuchsAdapter.Device_StopIdentify(Ant))
                    {
                        m_FuchsAdapter.Device_StopIdentify(Ant);
                    }
                    if (AntList[Ant - 1].IsReading)
                    {
                        m_FuchsAdapter.LogInfo.Info("》》》Receive_tagInf:IsReading = true");
                    }
                    else
                    {
                        m_FuchsAdapter.LogInfo.Info("》》》Receive_tagInf:IsReading = false");
                    }
                    AntList[Ant - 1].IsReading = false;
                    AntList[Ant - 1].readType = 0;
                    TagInventory = false;
                }

            }
        }

        private void Deal_UHFBeginIdentify(byte[] buffer, int iLen)
        {
            if (buffer[4] == 0XFF)
            {
                Array.Clear(buffer, 0, iLen);
                m_FuchsAdapter.LogInfo.Info("丢掉数据");
            }
            else
            {
                if (buffer[4] == 0X00)
                {
                  
                    Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);

                    lock (m_FrecvData)
                    {
                        m_FrecvData.Add(m_szFullMessage);
                    }
                    m_Fsem.Release();
                    m_FuchsAdapter.LogInfo.Info("接收自报数据丢进线程池，发送停止指令");
                    ThreadPool.QueueUserWorkItem(new WaitCallback(PareSend_UHFReceiveData), buffer); //超高频读头处理数据线程池
                }
                else
                {
                    Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);

                    lock (m_FrecvData)
                    {
                        m_FrecvData.Add(m_szFullMessage);
                    }
                    m_Fsem.Release();
                }
            }
        }

        private void PareSend_UHFReceiveData(object ReceiveData)    //超高频接收数据后发送停止指令
        {
            byte[] buffer = (byte[])ReceiveData;
            if (buffer[3] == 0X02)  //高频连续识别返回自报数据接收
            {
                if (m_FuchsAdapter != null)
                {
                    //LogService.Instance.Info("线程池5号天线发送停止指令");
                    m_FuchsAdapter.Device_StopIdentify(5); //处理函数
                }
            }
            else if (buffer[3] == 0X04)
            {
                if (m_FuchsAdapter != null)
                {
                    //LogService.Instance.Info("线程池6号天线发送停止指令");
                    m_FuchsAdapter.Device_StopIdentify(6); //处理函数
                }
            }
            else if (buffer[3] == 0X06)
            {
                if (m_FuchsAdapter != null)
                {
                    m_FuchsAdapter.Device_StopIdentify(7); //处理函数
                }
            }
            else if (buffer[3] == 0X08)
            {
                if (m_FuchsAdapter != null)
                {
                    m_FuchsAdapter.Device_StopIdentify(8); //处理函数
                }
            }
        }

        private void Deal_StopIdentify(byte[] buffer, int iLen)
        {
            if (buffer[4] == 0XFF)
            {
                Array.Clear(buffer, 0, iLen);
                m_FuchsAdapter.LogInfo.Info("丢掉数据");
            }
            else
            {
                Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
                lock (m_FrecvData)
                {
                    m_FrecvData.Add(m_szFullMessage);
                }
                m_Fsem.Release();
            }
        }

        private void Deal_HeartPack(byte[] buffer, int iLen)
        {

            Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);
            lock (m_FrecvData)
            {
                m_FrecvData.Add(m_szFullMessage);
            }
            m_Fsem.Release();

        }

        private void Deal_BeginIdentify(byte[] buffer, int iLen)
        {
            if (buffer[4] == 0XFF)
            {
                Array.Clear(buffer, 0, iLen);
                m_FuchsAdapter.LogInfo.Info("丢掉数据");
            }
            if (buffer[4] == 0X00)
            {
                Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);

                lock (m_FrecvData)
                {
                    m_FrecvData.Add(m_szFullMessage);
                }
                m_Fsem.Release();
                //switch (buffer[3])
                //{
                //    case 0X32:
                //        if (AntList[0].readType > 0)
                //        {
                //            AntList[0].ReadData = new byte[buffer.Length];
                //            Array.Copy(buffer, 0, AntList[0].ReadData, 0, buffer.Length);
                //        }
                //        break;
                //    case 0X34:
                //        if (AntList[1].readType > 0)
                //        {
                //            AntList[1].ReadData = new byte[buffer.Length];
                //            Array.Copy(buffer, 0, AntList[1].ReadData, 0, buffer.Length);
                //        }
                //        break;
                //    case 0X36:
                //        if (AntList[2].readType > 0)
                //        {
                //            AntList[2].ReadData = new byte[buffer.Length];
                //            Array.Copy(buffer, 0, AntList[2].ReadData, 0, buffer.Length);
                //        }
                //        break;
                //    case 0X38:
                //        if (AntList[3].readType > 0)
                //        {
                //            AntList[3].ReadData = new byte[buffer.Length];
                //            Array.Copy(buffer, 0, AntList[3].ReadData, 0, buffer.Length);
                //        }
                //        break;
                //}
                m_FuchsAdapter.LogInfo.Info("接收自报数据丢进线程池，发送停止指令");
                ThreadPool.QueueUserWorkItem(new WaitCallback(PareSend_ReceiveData), buffer); //超高频读头处理数据线程池
            }
            else
            {
                Array.Copy(buffer, 0, m_szFullMessage, 0, iLen);

                lock (m_FrecvData)
                {
                    m_FrecvData.Add(m_szFullMessage);
                }
                m_Fsem.Release();
            }
        }

        //CRC异或校验
        public byte CalculateVerify(byte[] pMessage, int iLength)
        {
            UInt16 i;
            byte iVerify = 0;

            iVerify = pMessage[0];
            for (i = 1; i < iLength; i++)
            {
                iVerify = (byte)(iVerify ^ pMessage[i]);
            }
            return iVerify;
        }
        private byte[] Swap16Bytes(byte[] OldU16)
        {
            byte[] ReturnBytes = new byte[2];
            ReturnBytes[1] = OldU16[0];
            ReturnBytes[0] = OldU16[1];
            return ReturnBytes;
        }

        private string bytesToHexStr(byte[] bytes, int iLen)//e.g. { 0x01, 0x01} ---> " 01 01"
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < iLen; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }
    }
}

