using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using System.ComponentModel;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using System.Net;
using Mesnac.Log;

namespace Mesnac.DeviceAdapter.RFly_I160
{
    public enum RecvState
    {
        //RFly-I160 返回数据 BB DD 00 01 40 41 0D
        WaitingBeginChar1_State = 1,         //等待接收帧同步字符1 0xBB
        WaitingBeginChar2_State = 2,         //等待接收帧同步字符2 0xDD
        WaitingForBarcodeLength_State = 3,  //等待条码长度不固定
        WaitingForCode_State = 4,           //等待指令编号Code 0x02
        WaitingForStus_State = 5,           //等待接受状态码 0x00
        WaitingForTagCount_State = 6,           //等待接受标签组数不固定
        WaitingForCount_State = 7,          //等待接收第一组标签读取次数 0x01
        WaitingForRSSI_State = 8,           //等待接收读取信号强度 0xCB
        WaitingForAnt_State = 9,           //等待接收天线端口 0x01
        WaitingForPC1_State = 10,           //等待接收EPC区域 0x00
        WaitingForPC2_State = 11,           //等待接收EPC区域 0x00
        WaitingForData_State = 12,          //等待接收数据字符
        WaitingForXor_State = 13,           //等待比对校验位
        WaitingForEndChar_State = 14,        //等待接收尾字符	0x0D
    };

    class BgTcpClient : ICommunicateService
    {
        RecvState enumRecvState = RecvState.WaitingBeginChar1_State;
        int m_iPosition = 0;
        UInt16 m_iFullMessageLength = 0;
        byte m_iVerify = 0;
        byte[] m_szFullMessage = new byte[1024];  //此数组用于状态机
        int iBarcodeGroupCount = 0; //读取的组数
        int iBarcodeLength = 0;//条码长度
        int iBarcodeGroupCountFlag = 0;//组数标记
        RFly_I160Adapter m_RFly_I160Adapter = null;
        public UInt16 m_iDeviceId = 0;
        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);

        //接收线程
        private void bgwReceive_DoWork(object sender, DoWorkEventArgs e)
        {
            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160 进入 bgwReceive_DoWork 线程函数：");
            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)
                        {
                            m_RFly_I160Adapter.LogInfo.Warn("》》》RFly-I160设备：" + m_iDeviceId +",IP:" + m_FsIP + ",接收原始报文:" + bytesToHexStr(buff, nCount));
                            PareReceiveData(buff, nCount); //调用状态机函数
                            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;
                    }
                }
                catch (Exception ex)
                {
                    e.Cancel = true;
                    if (m_ClientSock != null)
                    {
                        m_ClientSock.Close();
                        m_ClientSock = null;
                    }
                    m_RFly_I160Adapter.LogInfo.Warn("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 bgwDeal_DoWork(object sender, DoWorkEventArgs e)
        {
            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160 进入 bgwDeal_DoWork 线程：");
            while (true)
            {
                try
                {
                    m_Fsem.WaitOne();

                    lock (m_FrecvData)
                    {
                        if (m_FrecvData.Count > 0)
                        {
                            byte[] buff = (byte[])m_FrecvData[0];
                            if (m_RFly_I160Adapter != null)
                            {
                                m_RFly_I160Adapter.Device_DealValidPack(buff); //处理函数
                            }
                            m_FrecvData.RemoveAt(0);
                        }
                    }
                    if (Exitevent.WaitOne(0, false))
                    {
                        e.Cancel = true;
                        m_RFly_I160Adapter.LogInfo.Warn("Socket处理数据线程正常退出");
                        Exitevent.Reset();
                        return;
                    }
                }
                catch (Exception ex)
                {
                    e.Cancel = true;
                    m_RFly_I160Adapter.LogInfo.Warn("Socket处理数据异常： " + ex.ToString());
                    return;
                }
                if (this.m_bgwDeal.CancellationPending)
                {
                    m_RFly_I160Adapter.LogInfo.Warn("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
                Array.Copy(pMessagePack.m_pData, 0, SendBuffer, iPos, pMessagePack.m_pData.Length);   //数据域


                m_RFly_I160Adapter.LogInfo.Warn("》》》RFly-I160设备：" + m_iDeviceId + ",IP:"+ m_FsIP + ",发送原始报文:" + bytesToHexStr(SendBuffer, pMessagePack.m_pData.Length));
                int nCount = m_ClientSock.Send(SendBuffer, pMessagePack.m_pData.Length, SocketFlags.None);
                if (nCount > 0)   //发送成功
                {
                    //m_RFly_I160Adapter.LogInfo.Warn("m_ClientSock.Send函数发送成功");
                    return true;
                }
                else
                {
                    m_RFly_I160Adapter.LogInfo.Warn("连接已断开，数据发送失败");
                    return false;
                }
            }
            catch (Exception ex)
            {
                m_RFly_I160Adapter.LogInfo.Warn("发送报文异常: " + ex.ToString());
                return false;
            }
        }

        #region 初始化一套函数
        public bool Connect()
        {
            //连接       
            try
            {
                Exitevent.Reset();
                if (m_FsIP == "" || m_FnPort == 0)
                {
                    m_RFly_I160Adapter.LogInfo.Warn("IP和端口号不能为空，连接失败");
                    return false;
                }
                if (m_ClientSock != null && GetState())
                {
                    m_RFly_I160Adapter.LogInfo.Warn("已经连接了");
                    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
                    {
                        //启动接收线程  
                        //if (m_bgwReceive.IsBusy)
                        //{
                        //    return false;
                        //}
                        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_RFly_I160Adapter.LogInfo.Warn("创建后台线程异常 " + ex.ToString());
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                m_RFly_I160Adapter.LogInfo.Warn("Socket连接异常 " + ex.ToString());
                return false;
            }
        }

        public bool DisConnect()
        {
            try
            {
                Exitevent.Set();
                Thread.Sleep(100);
                m_Fsem.Release();
                if (m_ClientSock != null)
                {
                    m_ClientSock.Disconnect(false);
                    m_ClientSock.Close();
                    m_ClientSock = null;
                }
                return true;
            }
            catch (Exception ex)
            {
                m_RFly_I160Adapter.LogInfo.Warn("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,ushort DeviceId)
        {
            Exitevent.Reset();
            m_FsIP = strIp;
            m_FnPort = iPort;
            m_iDeviceId = DeviceId;
            m_RFly_I160Adapter = objetcter as RFly_I160Adapter;
        }
        #endregion

        //状态机函数
        public void PareReceiveData(byte[] buffer, int iLen)
        {
            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160进入状态机：");
            for (int i = 0; i < iLen; i++)
            {
                switch (enumRecvState)
                {
                    case RecvState.WaitingBeginChar1_State:         //开始接受数据帧1 0xBB
                        //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160等待接收帧同步字符WaitingBeginChar1_State:0XBB");
                        Array.Clear(m_szFullMessage, 0, 1024);//清空为0
                        if (buffer[i] == 0xBB)
                        {
                            //m_RFly_I160Adapter.LogInfo.Warn("Buffer数据为: " + StringChange.bytesToHexStr(buffer, buffer.Length));
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingBeginChar2_State;
                        }
                        else
                        {
                            m_iFullMessageLength = 0;
                            m_iPosition = 0;
                            enumRecvState = RecvState.WaitingBeginChar1_State;
                        }
                        break;
                    case RecvState.WaitingBeginChar2_State:             //开始接受数据帧1 0xDD
                        //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160等待接收帧同步字符WaitingBeginChar2_State:0XDD");
                        if (buffer[i] == 0xDD)
                        {
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForBarcodeLength_State;
                        }
                        else
                        {
                            m_iFullMessageLength = 0;
                            m_iPosition = 0;
                            enumRecvState = RecvState.WaitingBeginChar1_State;
                        }
                        break;
                    case RecvState.WaitingForBarcodeLength_State:         //开始接受数据长度(TagCount - EPC)                        
                        m_szFullMessage[m_iPosition] = buffer[i];
                        iBarcodeLength = buffer[i];                      //单组标签：18；两组标签：35
                        m_iPosition++;
                        enumRecvState = RecvState.WaitingForCode_State;
                        break;

                    case RecvState.WaitingForCode_State:                //开始接受指令编号
                        if (buffer[i] == 0x02)
                        {
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForStus_State;
                        }
                        else if (buffer[i] == 0x90)          // 如果是心跳BB DD 01 90 00 1F 8E 0D 
                        {
                            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160等待接受WaitingForEndChar_State:温度");
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForEndChar_State;
                        }
                        else if (buffer[i] == 0xBF)          // 如果是心跳BB DD 04 BF 00 00 00 F9 0B 49 0D
                        {
                            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160等待接受WaitingForEndChar_State:心跳");
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForEndChar_State;                           
                        }
                        else if (buffer[i] == 0x51)         
                        {
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForStus_State;
                        }
                        else
                        {
                            m_iFullMessageLength = 0;
                            m_iPosition = 0;
                            enumRecvState = RecvState.WaitingBeginChar1_State;
                        }
                        break;
                    case RecvState.WaitingForStus_State:        //开始接受状态码
                        if (buffer[i] == 0x00)
                        {
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForTagCount_State;
                        }
                        else if (buffer[i] == 0x40)
                        {
                            m_szFullMessage[m_iPosition] = buffer[i];
                            //m_RFly_I160Adapter.LogInfo.Warn("RFU620等待接受WaitingForEndChar_State:Noread");
                            lock (m_FrecvData)
                            {
                                m_FrecvData.Add(m_szFullMessage);
                            }
                            m_Fsem.Release();
                            m_iPosition = 0;
                            i = iLen;
                            enumRecvState = RecvState.WaitingBeginChar1_State;
                            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160状态机结束。");
                        }
                        break;
                    case RecvState.WaitingForTagCount_State:         //开始接受标签组数                        
                        Array.Copy(buffer, i, m_szFullMessage, m_iPosition, iBarcodeLength);//m_iPosition = 5
                        byte[] tempData = new byte[iBarcodeLength];
                        Array.Clear(tempData, 0, iBarcodeLength);
                        Array.Copy(buffer, i, tempData, 0, iBarcodeLength);
                        //m_RFly_I160Adapter.LogInfo.Warn("解析的数据为: " + StringChange.bytesToHexStr(tempData, iBarcodeLength));

                        //m_szFullMessage[m_iPosition] = buffer[i];   //单组标签：01；两组标签：02   
                        m_iPosition = m_iPosition + iBarcodeLength;     //m_iPosition = 39
                        i = i + iBarcodeLength -1;                         //i = 39
                        enumRecvState = RecvState.WaitingForXor_State;
                        break;
#region 暂时不需要
                    //case RecvState.WaitingForCount_State:

                    //    if (buffer[i] == 0x01)
                    //    {
                    //        m_szFullMessage[m_iPosition] = buffer[i];
                    //        m_iPosition++;
                    //        enumRecvState = RecvState.WaitingForRSSI_State;
                    //    }
                    //    else
                    //    {
                    //        m_iFullMessageLength = 0;
                    //        m_iPosition = 0;
                    //        enumRecvState = RecvState.WaitingBeginChar1_State;
                    //    }
                    //    break;

                    //case RecvState.WaitingForRSSI_State:         //开始接受功率
                    //    m_szFullMessage[m_iPosition] = buffer[i];
                    //    m_iPosition++;
                    //    enumRecvState = RecvState.WaitingForAnt_State;
                    //    break;

                    //case RecvState.WaitingForAnt_State:         //开始接受天线编号
                    //    m_szFullMessage[m_iPosition] = buffer[i];
                    //    m_iPosition++;
                    //    enumRecvState = RecvState.WaitingForPC1_State;
                    //    break;
                    //case RecvState.WaitingForPC1_State:
                    //    if (buffer[i] == 0x00)
                    //    {
                    //        m_szFullMessage[m_iPosition] = buffer[i];
                    //        m_iPosition++;
                    //        enumRecvState = RecvState.WaitingForPC2_State;
                    //    }
                    //    else
                    //    {
                    //        m_iFullMessageLength = 0;
                    //        m_iPosition = 0;
                    //        enumRecvState = RecvState.WaitingBeginChar1_State;
                    //    }
                    //    break;
                    //case RecvState.WaitingForPC2_State:
                    //    if (buffer[i] == 0x00)
                    //    {
                    //        m_szFullMessage[m_iPosition] = buffer[i];
                    //        m_iPosition++;
                    //        enumRecvState = RecvState.WaitingForData_State;
                    //    }
                    //    else
                    //    {
                    //        m_iFullMessageLength = 0;
                    //        m_iPosition = 0;
                    //        enumRecvState = RecvState.WaitingBeginChar1_State;
                    //    }
                    //    break;

                    //case RecvState.WaitingForData_State:
                    //    iBarcodeLength = 12;
                    //    Array.Copy(buffer, i, m_szFullMessage, m_iPosition, iBarcodeLength);
                    //    m_RFly_I160Adapter.LogInfo.Warn("RFly-I160进入 WaitingForData_State 状态，原始条码数据如下：");
                    //    byte[] tempData = new byte[iBarcodeLength];
                    //    Array.Clear(tempData, 0, iBarcodeLength);
                    //    Array.Copy(buffer, i, tempData, 0, iBarcodeLength);
                    //    m_RFly_I160Adapter.LogInfo.Warn("解析的数据为: "+StringChange.bytesToHexStr(tempData,iBarcodeLength));
                    //    m_iPosition = m_iPosition+iBarcodeLength;
                    //    i = i + iBarcodeLength - 1;
                    //    enumRecvState = RecvState.WaitingForXor_State;
                    //    break;
                    #endregion
                    case RecvState.WaitingForXor_State:         //开始比对校验位 Rfly160 
                        byte[] m_CRCVerify = new byte[1024];     //此数组用于校验位计算
                        Array.Clear(m_CRCVerify, 0, m_CRCVerify.Length);
                        Array.Copy(m_szFullMessage, 2, m_CRCVerify, 0, iBarcodeLength + 3); //校验位计算是从Length - EPC 结束
                        m_szFullMessage[m_iPosition] = buffer[i];
                        m_iVerify = m_szFullMessage[m_iPosition];
                        if (m_iVerify == CalculateVerify(m_CRCVerify, m_CRCVerify.Length))
                        {
                            m_iPosition++;
                            enumRecvState = RecvState.WaitingForEndChar_State;
                        }
                        else	   //如果校验不成功
                        {
                            m_iFullMessageLength = 0;
                            m_iPosition = 0;
                            enumRecvState = RecvState.WaitingBeginChar1_State;
                        }
                        break;
                    case RecvState.WaitingForEndChar_State:
                        if (buffer[0] == 0xBB && buffer[1] == 0xDD && buffer[2] == 0x00) //此处为Noread数据显示
                        {
                            //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160等待接受WaitingForEndChar_State:Noread");
                            m_szFullMessage[0] = 0xBB;
                            m_szFullMessage[1] = 0xDD;
                            m_szFullMessage[2] = 0x00;
                            lock (m_FrecvData)
                            {
                                m_FrecvData.Add(m_szFullMessage);
                            }
                            m_Fsem.Release();
                            m_iPosition = 0;
                            i = iLen;
                            enumRecvState = RecvState.WaitingBeginChar1_State;
                        }
                        else if (buffer[i] == 0x00)         //获取温度
                        {
                            m_szFullMessage[3] = 0x00;
                            m_iPosition++;
                            lock (m_FrecvData)
                            {
                                m_FrecvData.Add(m_szFullMessage);
                            }
                            m_Fsem.Release();
                        }
                        else if (buffer[0] == 0xBB && buffer[1] == 0xDD && buffer[2] == 0x04 && buffer[3] == 0xBF)
                        {
                            m_szFullMessage[3] = 0xBF;
                            m_iPosition++;
                            lock (m_FrecvData)
                            {
                                m_FrecvData.Add(m_szFullMessage);
                            }
                            m_Fsem.Release();
                        }
                        else
                        {
                            m_szFullMessage[m_iPosition] = buffer[i];
                            m_iPosition++;
                            if (buffer[i] == 0x0D)
                            {
                                //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160准备发送");
                                lock (m_FrecvData)
                                {
                                    m_FrecvData.Add(m_szFullMessage);
                                }
                                m_Fsem.Release();
                            }
                        }
                        m_iPosition = 0;
                        enumRecvState = RecvState.WaitingBeginChar1_State;
                        //m_RFly_I160Adapter.LogInfo.Warn("RFly-I160状态机结束。");
                        break;
                }
            }
        }
        //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;
        }
    }
}

