using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using iTekCAN;

namespace iTekCANFDDemon
{
    //接收数据线程类
    class recvdatathread
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate void RecvCANDataEventHandler(iTek_CANFD_Receive_DATA[] data, uint len);//CAN数据接收事件委托

       // [UnmanagedFunctionPointer(CallingConvention.StdCall)]
       // public delegate void RecvFDDataEventHandler(iTek_CANFD_DATA[] data, uint len);//CANFD数据接收事件委托

        const int TYPE_CAN = 0;
        const int TYPE_CANFD = 1;

        bool m_bStart;
        IntPtr channel_handle_;
        Thread recv_thread_;
        static object locker = new object();
        public static RecvCANDataEventHandler OnRecvCANDataEvent;
      //  public static RecvFDDataEventHandler OnRecvFDDataEvent;
        public recvdatathread()
        {
        }

        public event RecvCANDataEventHandler RecvCANData
        {
            add { OnRecvCANDataEvent += value; }
            remove { OnRecvCANDataEvent -= value; }
        }

       // public event RecvFDDataEventHandler RecvFDData
       // {
        //    add { OnRecvFDDataEvent += new RecvFDDataEventHandler(value); }
        //    remove { OnRecvFDDataEvent -= new RecvFDDataEventHandler(value); }
      //  }

        public void setStart(bool start)
        {
            m_bStart = start;
            if (start)
            {
                recv_thread_ = new Thread(RecvDataFunc);
                recv_thread_.IsBackground = true;
                recv_thread_.Start();
            }
            else
            {
                recv_thread_.Join();
                recv_thread_ = null;
            }
        }

        public void setChannelHandle(IntPtr channel_handle)
        {
            lock(locker)
            {
                channel_handle_ = channel_handle;
            }
        }

        //数据接收函数
        protected void RecvDataFunc()
        {
            iTek_CANFD_Receive_DATA[] can_data = new iTek_CANFD_Receive_DATA[256];
           // ZCAN_ReceiveFD_Data[] canfd_data = new ZCAN_ReceiveFD_Data[100];
            uint len;
            while (m_bStart)
            {
                lock (locker)
                {
                    len = iTekCanDLL.iTek_GetReceiveNum(channel_handle_);
                    Console.WriteLine("len = {0}", len);
                    
                    int size = Marshal.SizeOf(typeof(iTek_CANFD_Receive_DATA));
                    IntPtr ptr = Marshal.AllocHGlobal((int)len * size);
                    len = (uint)iTekCanDLL.iTek_Receive(channel_handle_, ptr, len, 0);
                     if (len > 0)
                    {
                        for (int i = 0; i < len; ++i)
                        {
                            can_data[i] = (iTek_CANFD_Receive_DATA)Marshal.PtrToStructure(
                                (IntPtr)((UInt32)ptr + i * size), typeof(iTek_CANFD_Receive_DATA));
                        }
                        OnRecvCANDataEvent(can_data, len);
                        Marshal.FreeHGlobal(ptr);
                    }
                    
                }
                Thread.Sleep(200);
            }
        }
    }
}

