using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LFP_Manager.Function
{
    // 1. Define the data type
    public struct PACKET_HEADER_DN
    {
        public byte Rsvd;           // 3
        public byte PR;             // 3 Priority
        public byte FC;             // 4 Function Code
        public byte NO;             // 8 Number
        public byte SID;            // 7 Source ID
        public byte DID;            // 7 Destination ID
    }

    public struct PACKET_DN
    {
        public UInt32 hdr;    // Header
        public byte[] data;             // Data
    }

    class csCanFwUpdateFunction
    {
        // Function Code Define 
        public const int DL_START_CODE              = 0;			    // Start Fw Update
        public const int DL_SECTOR_ERASE_CODE       = 1;			    // Sector Erase Code
        public const int DL_SET_ADDRESS_CODE        = 2;				// Flash Address Set Code
        public const int DL_READ_DATA_CODE          = 3;				// Flash Data Read Code
        public const int DL_WRITE_DATA_CODE         = 4;				// Flash Data Write Code
        public const int DL_WRITE_DATA_CSUM_CODE    = 5;				// Flash Data Write Checksum Code
        public const int DL_IMAGE_CSUM_CODE         = 6;				// Fw Image Checksum Code
        public const int DL_RESTART_CODE            = 7;				// Restart

        public static PACKET_HEADER_DN CovertPtoH(UInt32 id)
        {
            PACKET_HEADER_DN hdr = new PACKET_HEADER_DN();

            hdr.PR = (byte)((id >> 26) & 0x07);
            hdr.FC = (byte)((id >> 22) & 0x07);
            hdr.NO = (byte)((id >> 14) & 0xFF);
            hdr.SID = (byte)((id >> 7) & 0x7F);
            hdr.DID = (byte)((id >> 0) & 0x7F);

            return hdr;
        }

        public static UInt32 CovertHtoP(PACKET_HEADER_DN hdr)
        {
            UInt32 Packet = 0;

            Packet = (((UInt32)hdr.PR << 26)
                | ((UInt32)hdr.FC << 22)
                | ((UInt32)hdr.NO << 14)
                | ((UInt32)hdr.SID << 7)
                | ((UInt32)hdr.DID << 0)
                );
            return Packet;
        }

        unsafe public static PACKET_DN FwUpdateStartPacket(UInt32 dev_id, byte[] fwver, UInt32 fwlen)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_START_CODE;
            hdr.NO = 0;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            result.data[0] = fwver[0];
            result.data[1] = fwver[1];
            result.data[2] = fwver[2];
            result.data[3] = fwver[3];

            result.data[4] = (byte)(fwlen >> 24);
            result.data[5] = (byte)(fwlen >> 16);
            result.data[6] = (byte)(fwlen >> 8);
            result.data[7] = (byte)(fwlen >> 0);

            return result;
        }

        unsafe public static PACKET_DN SectorErasePacket(UInt32 dev_id, UInt32 fAddr)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_SECTOR_ERASE_CODE;
            hdr.NO = 0;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            result.data[0] = (byte)(fAddr >> 24);
            result.data[1] = (byte)(fAddr >> 16);
            result.data[2] = (byte)(fAddr >> 8);
            result.data[3] = (byte)(fAddr >> 0);

            result.data[4] = 0;
            result.data[5] = 0;
            result.data[6] = 0;
            result.data[7] = 0;

            return result;
        }

        unsafe public static PACKET_DN SetAddrPacket(UInt32 dev_id, UInt32 sAddr, UInt32 sLen)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_SET_ADDRESS_CODE;
            hdr.NO = 0;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            result.data[0] = (byte)(sAddr >> 24);
            result.data[1] = (byte)(sAddr >> 16);
            result.data[2] = (byte)(sAddr >> 8);
            result.data[3] = (byte)(sAddr >> 0);

            result.data[4] = (byte)(sLen >> 24);
            result.data[5] = (byte)(sLen >> 16);
            result.data[6] = (byte)(sLen >> 8);
            result.data[7] = (byte)(sLen >> 0);

            return result;
        }

        unsafe public static PACKET_DN WritePacket(UInt32 dev_id, byte dno, byte[] data)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_WRITE_DATA_CODE;
            hdr.NO = dno;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            for (int i = 0; i < 8; i++)
            {
                result.data[i] = data[i];
            }

            return result;
        }

        unsafe public static PACKET_DN WriteChkSumPacket(UInt32 dev_id, UInt32 waddr, UInt32 csum)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_WRITE_DATA_CSUM_CODE;
            hdr.NO = 0;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            result.data[0] = (byte)(waddr >> 24);
            result.data[1] = (byte)(waddr >> 16);
            result.data[2] = (byte)(waddr >> 8);
            result.data[3] = (byte)(waddr >> 0);

            result.data[4] = (byte)(csum >> 24);
            result.data[5] = (byte)(csum >> 16);
            result.data[6] = (byte)(csum >> 8);
            result.data[7] = (byte)(csum >> 0);

            return result;
        }

        unsafe public static PACKET_DN FwImageChkSumPacket(UInt32 dev_id, UInt32 fwlen, UInt32 csum)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_IMAGE_CSUM_CODE;
            hdr.NO = 0;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            result.data[0] = (byte)(fwlen >> 24);
            result.data[1] = (byte)(fwlen >> 16);
            result.data[2] = (byte)(fwlen >> 8);
            result.data[3] = (byte)(fwlen >> 0);

            result.data[4] = (byte)(csum >> 24);
            result.data[5] = (byte)(csum >> 16);
            result.data[6] = (byte)(csum >> 8);
            result.data[7] = (byte)(csum >> 0);

            return result;
        }

        unsafe public static PACKET_DN UpdateRestartPacket(UInt32 dev_id, byte option)
        {
            PACKET_DN result;
            PACKET_HEADER_DN hdr;

            result = new PACKET_DN();
            result.data = new byte[8];

            hdr = new PACKET_HEADER_DN();

            hdr.PR = 4;
            hdr.FC = DL_RESTART_CODE;
            hdr.NO = 0;
            hdr.SID = 0;
            hdr.DID = (byte)dev_id;

            result.hdr = CovertHtoP(hdr);

            result.data[0] = option;
            result.data[1] = 0x00;
            result.data[2] = 0x00;
            result.data[3] = 0x00;

            result.data[4] = 0x00;
            result.data[5] = 0x00;
            result.data[6] = 0x00;
            result.data[7] = 0x00;

            return result;
        }
    }
}
