using System;
using System.Runtime.InteropServices;

namespace ZLGCAN
{
    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN
    {
        public uint acc_code;
        public uint acc_mask;
        public uint reserved;
        public byte filter;
        public byte timing0;
        public byte timing1;
        public byte mode;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct CANFD
    {
        public uint acc_code;
        public uint acc_mask;
        public uint abit_timing;
        public uint dbit_timing;
        public uint brp;
        public byte filter;
        public byte mode;
        public UInt16 pad;
        public uint reserved;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct can_frame
    {
        public uint can_id;  /* 32 bit MAKE_CAN_ID + EFF/RTR/ERR flags */
        public byte can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
        public byte __pad;   /* padding */
        public byte __res0;  /* reserved / padding */
        public byte __res1;  /* reserved / padding */
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] data/* __attribute__((aligned(8)))*/;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct canfd_frame
    {
        public uint can_id;  /* 32 bit MAKE_CAN_ID + EFF/RTR/ERR flags */
        public byte len;     /* frame payload length in byte */
        public byte flags;   /* additional flags for CAN FD,i.e error code */
        public byte __res0;  /* reserved / padding */
        public byte __res1;  /* reserved / padding */
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] data/* __attribute__((aligned(8)))*/;
    };

    [StructLayout(LayoutKind.Explicit)]
    public struct ZCAN_CHANNEL_INIT_CONFIG
    {
        [FieldOffset(0)]
        public uint can_type; //type:TYPE_CAN TYPE_CANFD

        [FieldOffset(4)]
        public ZCAN can;

        [FieldOffset(4)]
        public CANFD canfd;
    };


    // 定义结构体布局
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct ZCAN_DEVICE_INFO
    {
        public ushort hw_Version; // 硬件版本
        public ushort fw_Version; // 固件版本
        public ushort dr_Version; // 驱动版本
        public ushort in_Version; // 动态库版本
        public ushort irq_Num;
        public byte can_Num;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
        public byte[] str_Serial_Num;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
        public byte[] str_hw_Type;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public ushort[] reserved;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN_Transmit_Data
    {
        public can_frame frame;
        public uint transmit_type;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN_Receive_Data
    {
        public can_frame frame;
        public UInt64 timestamp;//us
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN_TransmitFD_Data
    {
        public canfd_frame frame;
        public uint transmit_type;
    };




    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN_AUTO_TRANSMIT_OBJ     //CAN定时发送帧结构体
    {
        public ushort enable;           //0-禁用，1-使能  
        public ushort index;            //定时报文索引  
        public uint interval;                  //定时周期
        public ZCAN_Transmit_Data  obj;
    };


    [StructLayout(LayoutKind.Sequential)]
    public struct ZCANFD_AUTO_TRANSMIT_OBJ    //CANFD定时发送帧结构体
    {
        public ushort enable;           //0-禁用，1-使能  
        public ushort index;            //定时报文索引  
        public uint interval;                  //定时周期
        public ZCAN_TransmitFD_Data obj;
    };



    public struct DeviceInfo
    {
        public uint device_type;  //设备类型
        public uint channel_count;//设备的通道个数
        public DeviceInfo(uint type, uint count)
        {
            device_type = type;
            channel_count = count;
        }
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN_ReceiveFD_Data
    {
        public canfd_frame frame;
        public UInt64 timestamp;//us
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct ZCAN_CHANNEL_ERROR_INFO
    {
        public uint error_code;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
        public byte[] passive_ErrData;
        public byte arLost_ErrData;
    } ;

    //for zlg cloud
    [StructLayout(LayoutKind.Sequential)]
    public struct ZCLOUD_CHNINFO
    {
        public byte enable;
        public byte type;
        public byte isUpload;
        public byte isDownload;
    };



    //for zlg cloud
    [StructLayout(LayoutKind.Sequential)]
    public struct ZCLOUD_DEVINFO
    {
        public int devIndex;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] type;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] id;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] name;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] owner;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] model;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public char[] fwVer;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public char[] hwVer;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] serial;
        public int status;             // 0:online, 1:offline
        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte bGpsUploads;
        public byte channelCnt;   // each channel enable can upload
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public ZCLOUD_CHNINFO[] channels;

    };

    //[StructLayout(LayoutKind.Sequential)]
    //public struct ZCLOUD_DEV_GROUP_INFO
    //{
    //    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    //    public char[] groupName;
    //    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    //    public char[] desc;
    //    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    //    public char[] groupId;
    //    //public ZCLOUD_DEVINFO *pDevices;
    //    public IntPtr pDevices;
    //    public uint devSize;
    //};

    [StructLayout(LayoutKind.Sequential)]
    public struct ZCLOUD_USER_DATA
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] username;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public char[] mobile;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public char[] dllVer;

        public uint devCnt;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        public ZCLOUD_DEVINFO[] devices;

    };

    public class Define
    {
        public const int TYPE_CAN = 0;
        public const int TYPE_CANFD = 1; 

        
    
        public const int ZCAN_UCANFD_400U = 201;
        public const int ZCAN_UCAN_401U = 200;



        public const int ZCAN_USBCAN1 = 3;
        public const int ZCAN_USBCAN2 = 4;

        public const int ZCAN_USBCANFD_200U = 41;
        public const int ZCAN_USBCANFD_100U = 42;


        public const int ZCAN_CANETUDP = 12;
        public const int ZCAN_CANETTCP = 17;
        public const int ZCAN_USBCAN_E_U = 20;
        public const int ZCAN_USBCAN_2E_U = 21;

        public const int ZCAN_PCIECANFD_100U = 38;
        public const int ZCAN_PCIECANFD_200U = 39;

        public const int ZCAN_PCIECANFD_200U_EX = 62;
        public const int ZCAN_PCIECANFD_400U = 61;



        public const int ZCAN_USBCANFD_MINI = 43;

        public const int ZCAN_CLOUD = 46;
        public const int ZCAN_CANFDNET_200U_TCP = 48;
        public const int ZCAN_CANFDNET_200U_UDP = 49;
        public const int ZCAN_CANFDNET_400U_TCP = 52;
        public const int ZCAN_CANFDNET_400U_UDP = 53;
        public const int ZCAN_CANFDNET_800U_TCP = 57;
        public const int ZCAN_CANFDNET_800U_UDP = 58;



        public const int STATUS_ERR = 0;
        public const int STATUS_OK = 1;
    };

    public class Method
    {
        //@-"D:\work\c_and\Usb_Can_Dll\Debug\Usb_Can_Dll.dll"

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr ZCAN_OpenDevice(uint device_type, uint device_index, uint reserved);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_CloseDevice(IntPtr device_handle);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int SET_SLEEP_WEEK_TIME(int week_time);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        // pInitConfig -> ZCAN_CHANNEL_INIT_CONFIG
        public static extern IntPtr ZCAN_InitCAN(IntPtr device_handle, uint can_index, IntPtr pInitConfig);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_IsDeviceOnLine(IntPtr device_handle);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_SetValue(IntPtr device_handle,string path  , byte[] value);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_SetValue(IntPtr device_handle, string path, IntPtr value);


        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_StartCAN(IntPtr channel_handle);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_ResetCAN(IntPtr channel_handle);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        // pTransmit -> ZCAN_Transmit_Data
        public static extern uint ZCAN_Transmit(IntPtr channel_handle, IntPtr pTransmit, uint len);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        // pTransmit -> ZCAN_TransmitFD_Data
        public static extern uint ZCAN_TransmitFD(IntPtr channel_handle, IntPtr pTransmit, uint len);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_GetReceiveNum(IntPtr channel_handle, byte type);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_Receive(IntPtr channel_handle, IntPtr data, uint len, int wait_time = -1);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_ReceiveFD(IntPtr channel_handle, IntPtr data, uint len, int wait_time = -1);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        // pErrInfo -> ZCAN_CHANNEL_ERROR_INFO
        public static extern uint ZCAN_ReadChannelErrInfo(IntPtr channel_handle, IntPtr pErrInfo);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetIProperty(IntPtr device_handle);

        [DllImport("zlgcan.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern uint ZCAN_GetDeviceInf(IntPtr channel_handle, IntPtr pInfo);
        
    }

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int SetValueFunc(string path, byte[] value);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate IntPtr GetValueFunc(string path);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate IntPtr GetPropertysFunc(string path, string value);

    public struct IProperty
    {
        public SetValueFunc SetValue;
        public GetValueFunc GetValue;
        public GetPropertysFunc GetPropertys;
    };
}
