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

namespace Jdas_Mbic
{
    public enum Bluepro_t
    {
        bluecell_header0 = 0,
        bluecell_header1,
        bluecell_header2,
        bluecell_header3,
        bluecell_type,
        bluecell_length_h,
        bluecell_length_l,
        bluecell_updatecnt_h,
        bluecell_updatecnt_l,
        bluecell_data,

    };
    public enum Updateseq
    {
        Bluecell_Reset = 0,
        Bluecell_Firmupdate_start,
        Bluecell_Firmupdate_sending,
        Bluecell_Firmupdate_end,
    };
    enum Bluecell_ProtIndex_p
    {
        Bluecell_Header = 0,
        Bluecell_Type,
        Bluecell_Length,
        Bluecell_CrcIndex,
        Bluecell_data,
    }
    enum Bluecell_Prot_t{
        TYPE_BLUECELL_RESET = 0,
        TYPE_BLUECELL_SET   = 1,
        TYPE_BLUECELL_GET   = 2,
        TYPE_BLUECELL_SAVE  = 3,
        TYPE_BLUECELL_ACK   = 4,
    };
    class Bluecell_BootProtocol
    {
        Serial serial;
        /*bluecell Header*/
        public const byte Bluecell_Header0 = 0x42;//ASCII : B
        public const byte Bluecell_Header1 = 0x4C;//ASCII : L
        public const byte Bluecell_Header2 = 0x55;//ASCII : U
        public const byte Bluecell_Header3 = 0x45;//ASCII : E
        /*bluecell type*/


        public const int bluecell_Firmupdate_sendlength = 1024;
        Crc16 crc16 = new Crc16();
        public const byte BLUECELL_HEADER = 0xBE;
        public const byte BLUECELL_TAILER = 0xEB;
        const byte BLUECELL_RESET_LENGTH = 6;
        const byte BLUECELL_FIX_DATA_LENGTH = 3;
        public void Bluecell_Reset(object serial)
        {
            this.serial = (Serial)serial;
            byte[] temp_buf = new byte[BLUECELL_RESET_LENGTH];
            temp_buf[(int)Bluecell_ProtIndex_p.Bluecell_Header]       = BLUECELL_HEADER;
            temp_buf[(int)Bluecell_ProtIndex_p.Bluecell_Type]         = (byte)Bluecell_Prot_t.TYPE_BLUECELL_RESET;
            temp_buf[(int)Bluecell_ProtIndex_p.Bluecell_Length]       = BLUECELL_RESET_LENGTH - BLUECELL_FIX_DATA_LENGTH;
            temp_buf[(int)Bluecell_ProtIndex_p.Bluecell_CrcIndex]     = (byte)Bluecell_ProtIndex_p.Bluecell_data;
            temp_buf[(int)Bluecell_ProtIndex_p.Bluecell_data]         = crc16.STH30_CreateCrc(temp_buf, BLUECELL_RESET_LENGTH - 3);
            temp_buf[(int)Bluecell_ProtIndex_p.Bluecell_data + 1]     = BLUECELL_TAILER;
            this.serial.Serial_DataSend(temp_buf, temp_buf.Length);
        }

        public const byte bluecell_length    = 2;
        public const byte bluecell_updatecnt = 2;
        public const byte bluecell_crc16     = 2;
     
   

#if false
        public int Bluecell_Firmupdate_sendlength() {
            return bluecell_Firmupdate_sendlength;
        }
        private void BootHeaderput(ref byte[] fix_data)
        {
            fix_data[(int)Bluepro_t.bluecell_header0] = Bluecell_Header0;
            fix_data[(int)Bluepro_t.bluecell_header1] = Bluecell_Header1;
            fix_data[(int)Bluepro_t.bluecell_header2] = Bluecell_Header2;
            fix_data[(int)Bluepro_t.bluecell_header3] = Bluecell_Header3;
        }

        public byte[] Boot_Reset(object serial,byte[] Updatedata)
        {
            this.serial = (Serial)serial;
            byte[] fix_data = new byte[11];
            //Array.Clear(data, 0, data.Length);
            BootHeaderput(ref fix_data);
            fix_data[(int)Bluepro_t.bluecell_type]    = (byte)Updateseq.Bluecell_Reset;
            fix_data[(int)Bluepro_t.bluecell_length_h]  = 0;
            fix_data[(int)Bluepro_t.bluecell_length_l]  = 5;
            fix_data[(int)Bluepro_t.bluecell_updatecnt_h] = Convert.ToByte((Updatedata.Length & 0xFF00) >> 8);
            fix_data[(int)Bluepro_t.bluecell_updatecnt_l] = Convert.ToByte((Updatedata.Length & 0x00FF));

            fix_data[(int)Bluepro_t.bluecell_data + 0] = Convert.ToByte((crc16.CRC16_Generate(fix_data, fix_data.Length - 4) & 0xFF00) >> 8);
            fix_data[(int)Bluepro_t.bluecell_data + 1] = Convert.ToByte((crc16.CRC16_Generate(fix_data, fix_data.Length - 4) & 0x00FF));
            this.serial.Serial_DataSend(fix_data, fix_data.Length);
            return fix_data;            
        }
     
        public byte[] Boot_DataSending(byte[] update_data,UInt16 length, UInt16 updatacnt)
        {
            //Array.Clear(data, 0, data.Length);
            byte[] fix_data = new byte[bluecell_Firmupdate_sendlength];
            //BootHeaderput(ref fix_data);
            //length += 5;
            Array.Copy(update_data, (int)Bluepro_t.bluecell_data, fix_data, (int)Bluepro_t.bluecell_data, length);
            BootHeaderput(ref fix_data);
            fix_data[(int)Bluepro_t.bluecell_type] = (byte)Updateseq.Bluecell_Firmupdate_sending;
            fix_data[(int)Bluepro_t.bluecell_length_h] = Convert.ToByte((length & 0xFF00) >> 8);
            fix_data[(int)Bluepro_t.bluecell_length_l] = Convert.ToByte((length & 0x00FF));
            fix_data[(int)Bluepro_t.bluecell_updatecnt_h] = Convert.ToByte((updatacnt & 0xFF00) >> 8);
            fix_data[(int)Bluepro_t.bluecell_updatecnt_l] = Convert.ToByte((updatacnt & 0x00FF));

            //Array.Copy(update_data, 0, fix_data, (int)Bluepro_t.bluecell_data, length-3);
            fix_data[length + 9] = Convert.ToByte((crc16.CRC16_Generate(fix_data, length + 5) & 0xFF00) >> 8);
            fix_data[length + 10] = Convert.ToByte(crc16.CRC16_Generate(fix_data, length + 5) & 0x00FF);
            return fix_data;
        }
        public byte[] Boot_DataEnd(byte[] update_data, int length)
        {
            //Array.Clear(data, 0, data.Length);
            byte[] fix_data = new byte[11];
            Array.Copy(update_data, (int)Bluepro_t.bluecell_data, fix_data, (int)Bluepro_t.bluecell_data, length);
            BootHeaderput(ref fix_data);
            fix_data[(int)Bluepro_t.bluecell_type]    = (byte)Updateseq.Bluecell_Firmupdate_end;
            fix_data[(int)Bluepro_t.bluecell_length_h] = Convert.ToByte((length & 0xFF00) >> 8);
            fix_data[(int)Bluepro_t.bluecell_length_l] = Convert.ToByte((length & 0x00FF));
            fix_data[(int)Bluepro_t.bluecell_updatecnt_h] = 0;
            fix_data[(int)Bluepro_t.bluecell_updatecnt_l] = 0;

            //Array.Copy(update_data, 0, fix_data, (int)Bluepro_t.bluecell_data, length-3);
            fix_data[length + 9] = Convert.ToByte((crc16.CRC16_Generate(fix_data, length + 5) & 0xFF00) >> 8);
            fix_data[length + 10] = Convert.ToByte(crc16.CRC16_Generate(fix_data, length + 5) & 0x00FF);
            return fix_data;
        }
#endif
    }
}
