using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Runtime.InteropServices;

namespace GcDevicePc.ProThread
{
    class DataRcv
    {
        
        static ManualResetEvent rcvdatamre = new ManualResetEvent(false);
        Thread t_DataRcv;

        static byte[] buffer = new byte[1024*1024];  
        static List<UInt32> data = new List<UInt32>();
        static bool dataflag = false;
        static bool recvend = false;

       // static bool threadrestart = false;
       // static bool lastthreadend = false;

        private static void DataRcv_Work()
        {
            try
            {
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
               // int id = Thread.CurrentThread.ManagedThreadId;
               // Console.WriteLine("当前线程{0:X}", id);

                while(true)
                {                  
                    while(true)
                    {
                        try
                        {
                            if (!String.IsNullOrEmpty(globaldata.connection_ip))
                                socket.Connect(globaldata.connection_ip, 8005); //配置服务器IP与端口  
                             Console.WriteLine("连接服务器成功");
                             break;
                        }
                        catch
                        {
                            Console.WriteLine("连接服务器失败，请按回车键退出!");
                        }

                        Thread.Sleep(2000);
                    }

                    try
                    {
                        Thread.Sleep(500);
                        string sendMessage = "ok";
                        socket.Send(Encoding.ASCII.GetBytes(sendMessage));
                        Console.WriteLine("向服务器发送消息：{0}" + sendMessage);
                        break;
                    }
                    catch
                    {
                        socket.Shutdown(SocketShutdown.Both);
                        socket.Close();
                    }
                    Thread.Sleep(1000);
                }

                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);

            }
            catch 
            {
               
            }
            finally
            {
                
            }  
        }

        /// <summary>
        /// 所有数据接收完毕存储数据
        /// </summary>
        private static void RecordData()
        {
            UInt32[] tmpdata = new UInt32[1];
            float[] f = new float[1];
            int i;
            lock (globaldata.m_signalbuffer.TCP_Port)
            {
            globaldata.m_signalbuffer.TCP_Port.Clear();

            for (i = 0; i < data.Count; i += 4)
            {
                try
                {
                    tmpdata[0] = data[i];
                    Buffer.BlockCopy(tmpdata, 0, f, 0, 4);
                    fidv[0] = f[0];

                    tmpdata[0] = data[i + 1];
                    Buffer.BlockCopy(tmpdata, 0, f, 0, 4);
                    fidv[1] = f[0];

                    tmpdata[0] = data[i + 2];
                    Buffer.BlockCopy(tmpdata, 0, f, 0, 4);
                    fidv[2] = f[0];

                    globaldata.m_signalbuffer.TCPChannel_Port.dettimer = data[i + 3];
                    globaldata.m_signalbuffer.TCPChannel_Port.detdata1 = fidv[0];
                    globaldata.m_signalbuffer.TCPChannel_Port.detdata2 = fidv[1];
                    globaldata.m_signalbuffer.TCPChannel_Port.detdata3 = fidv[2];

                    globaldata.m_signalbuffer.TCP_Port.Add(globaldata.m_signalbuffer.TCPChannel_Port);
                }
            
                catch
                {

                }
            }
            }
        }


        private static void ReceiveMessage(IAsyncResult ar)
        {
            try
            {
                //Console.WriteLine("ReceiveMessage=========");
                var socket = ar.AsyncState as Socket;
                int length = socket.EndReceive(ar);   
                var message = Encoding.ASCII.GetString(buffer, 0, length);
               
                ChangeBuff(buffer, length);               
                lock(buffer){

                    if (!rcvdatamre.WaitOne(10))
                    {
                        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
                    }
                    else
                    {
                        Console.WriteLine("老线程退出！");
                     //   lastthreadend = true;
                    }
                }

                if (recvend)
                {
                    RecordData();
                    recvend = false;
                }
            }
            catch (Exception ex)
            {
               Console.WriteLine(ex.Message);
            //   threadrestart = true;
               var socket = ar.AsyncState as Socket;
               socket.Shutdown(SocketShutdown.Both);
               socket.Close();
               DataRcv_Work();
            }
        }

        private static UInt32 datalen = 0;
        private static UInt32 checkend = 0;
        private static System.UInt16[] lastdata = new System.UInt16[8];
        private static float[] fidv = new float[3];
        private static UInt32 checkpackage = 0;

        private static void parseStartData(byte[] buffer, int len)
        {
            if(dataflag == false)
            {
                if(len == 0x10)
                {
                    lastdata[0] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[3], buffer[2]), System.Globalization.NumberStyles.HexNumber);
                    lastdata[1] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[1], buffer[0]), System.Globalization.NumberStyles.HexNumber);

                    lastdata[6] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[15], buffer[14]), System.Globalization.NumberStyles.HexNumber);
                    lastdata[7] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[13], buffer[12]), System.Globalization.NumberStyles.HexNumber);

                    checkpackage = lastdata[0];
                    checkpackage <<= 16;
                    checkpackage = checkpackage + lastdata[1];

                    if (checkpackage == 0x37)
                    {
                        datalen = lastdata[6];
                        datalen <<= 16;
                        datalen = datalen + lastdata[7];

                        datalen *= 16;
                        datalen += 0x10;
                        dataflag = true;
                        data.Clear();
                    }                   
                }
            }
        }

        private static void parseData(byte[] buffer, int len)
        {
            UInt32 valtmp;
            int i;
            if (dataflag == true)
            {
                for (i = 0; i < len; i += 4)
                {
                    lastdata[0] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[i + 3], buffer[i + 2]), System.Globalization.NumberStyles.HexNumber);
                        lastdata[1] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[i + 1], buffer[i]), System.Globalization.NumberStyles.HexNumber);

                        valtmp = lastdata[0];
                        valtmp <<= 16;
                        valtmp = valtmp + lastdata[1];

                        data.Add(valtmp);
                }
            }
        }

        private static void parseEndData(byte[] buffer, int len)
        {
            if (dataflag == true)
            {
                if (len == 0x10)
                {
                    lastdata[0] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[3], buffer[2]), System.Globalization.NumberStyles.HexNumber);
                    lastdata[1] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[1], buffer[0]), System.Globalization.NumberStyles.HexNumber);

                    lastdata[2] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[7], buffer[6]), System.Globalization.NumberStyles.HexNumber);
                    lastdata[3] = UInt16.Parse(string.Format("{0:X2}{1:X2}", buffer[5], buffer[4]), System.Globalization.NumberStyles.HexNumber);


                    checkpackage = lastdata[0];
                    checkpackage <<= 16;
                    checkpackage = checkpackage + lastdata[1];

                     if (checkpackage == 0x37)
                     {
                         checkend = lastdata[2];
                         checkend <<= 16;
                         checkend = checkend + lastdata[3];

                         if(checkend == 0xFFFFFFFF)
                         {
                             dataflag = false;
                             recvend = true;
                         }
                     }
                }
            }
        }

        private static void ChangeBuff(byte[] buffer, int len )
        {
            byte[] endpackage = new byte[16];

            if(dataflag == false)
            {
                if (len > 0)
                {                  
                    parseStartData(buffer,len);
                }
            }
            else
            {                
                if (len > 0 && datalen >= len)
                {
                    datalen = (UInt32)(datalen - len);

                    if (datalen == 0x0)
                    {
                       // Console.WriteLine("最后一帧！");
                        parseData(buffer, (len-0x10));
         
                        Buffer.BlockCopy(buffer, (len - 0x10), endpackage, 0, 0x10);

                        parseEndData(endpackage, 0x10);
                        //Console.WriteLine("最后一帧！结束");
                    }
                    else
                    {
                        parseData(buffer, len);
                    }

                    //datacount++;                 
                }
            }
        }

        public void DataRcvStart()
        {
            if (rcvdatamre != null)
            {
                rcvdatamre.Reset();
            }

            t_DataRcv = new Thread(DataRcv_Work);
            t_DataRcv.IsBackground = true;
            t_DataRcv.Start();
        }

        public void DataRcvStop()
        {
            rcvdatamre.Set();
        }
    }
}
