using DevExpress.XtraEditors;
using DevExpress.XtraRichEdit.Import.Doc;
using LFP_Manager.DataStructure;
using LFP_Manager.Function;
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 static DevExpress.Xpo.Helpers.AssociatedCollectionCriteriaHelper;

namespace LFP_Manager.Controls
{
    public partial class UcAntiTheftControl : DevExpress.XtraEditors.XtraUserControl
    {
        #region DELEGATE

        public delegate void setCalibUpdate(object sender);
        public delegate void setCalibCommand(int mode, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib);
        public delegate Int32 getBattData(int item, int cno);

        #endregion

        #region VARIABLES

        private int SystemId = 0;
        private const int CALC_INDEX = 6;

        private DeviceParamData rParam;

        private DeviceCalibration rCalib;
        private DeviceCalibration wCalib;

        public event setCalibCommand OnCommand = null;
        public event getBattData OnGetBattData = null;

        public event SendDataUartEvent OnSendUartData = null;

        #endregion

        #region CONSTRUCTORS
        public UcAntiTheftControl()
        {
            InitializeComponent();

            TmrDisplay.Enabled = true;
        }
        #endregion

        #region EXT EVENT FUNCTION

        private void OnCommnadEvent(int mode, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib)
        {
            OnCommand?.Invoke(mode, index, flag, ref aParam, ref aCalib);
        }

        private Int32 OnGetBattDataEvent(int item, int cno)
        {
            Int32 result = 0;

            if (OnGetBattData != null)
            {
                result = OnGetBattData(item, cno);
            }
            return result;
        }

        #endregion

        #region PUBLIC FUCTIONS

        public void UpdateData(int sId, DeviceCalibration aCalib)
        {
            SystemId = sId;
            rCalib = aCalib;
        }

        #endregion

        #region DISPLAY DATA

        private void DisplayAntiTheft()
        {
            if (rCalib != null)
            {
                TeTimeOutSet.Text = string.Format("{0}", rCalib.AntiTheftComm.TimeOut);
                TeFunctionSwitch.Text = string.Format("{0}", rCalib.AntiTheftComm.FuncSwitch);

                TeGyroXAxis.Text = string.Format("{0}", rCalib.AntiTheftGyro.XAxis);
                TeGyroYAxis.Text = string.Format("{0}", rCalib.AntiTheftGyro.YAxis);
                TeGyroZAxis.Text = string.Format("{0}", rCalib.AntiTheftGyro.ZAxis);

                TeGyroPolSel.Text = string.Format("{0}", rCalib.AntiTheftGyro.GyroPolicySel);
                TeGyroFunctionSwitch.Text = string.Format("{0}", rCalib.AntiTheftGyro.GyroFuncSwitch);
                TeGyroState.Text = string.Format("{0}", rCalib.AntiTheftGyro.GyroState);
            }
        }

        #endregion

        #region BUTTON EVENT
        private void BtnCommUnlock_Click(object sender, EventArgs e)
        {
            AntiTheftCommParamWrite(0x3001, 0);
        }

        private void BtnATCommTimeoutSet_Click(object sender, EventArgs e)
        {
            if (TeTimeOutSetNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeTimeOutSetNew.Text);
                AntiTheftCommParamWrite(0x3000, tmp);
            }
        }

        private void BtnATCommFuncSwSet_Click(object sender, EventArgs e)
        {
            if (TeFunctionSwitchNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeFunctionSwitchNew.Text);
                AntiTheftCommParamWrite(0x3002, tmp);
            }
        }

        private void BtnGyroUnlock_Click(object sender, EventArgs e)
        {
            GyroScopeParamWrite(0x4007, 1);
        }

        private void MultiDateWriteCmd(ushort addr, int data, int len)
        {
            byte[] crc;
            int i = 0;
            // Normal mode --> Bootloader mode
            byte[] sdata = new byte[7 + 2 + 2];

            sdata[i++] = (byte)SystemId;                  // Device ID
            sdata[i++] = (byte)CsSerialCommFunctionDelta.PRESET_MULTI_REG;         // Command
            sdata[i++] = (byte)(addr >> 8);       // Write Register Address MSB
            sdata[i++] = (byte)(addr >> 0);       // Write Register Address LSB
            sdata[i++] = (byte)(1 >> 8);               // Write Count of Register MSB
            sdata[i++] = (byte)(1 >> 0);               // Write Count of Register LSB
            sdata[i++] = (byte)(1 * 2);                // Byte Count - [2 * (Num of register)]

            sdata[i++] = (byte)(data >> 8);
            sdata[i++] = (byte)(data >> 0);

            crc = CsSerialCommFunctionDelta.GetCRC(sdata, i);

            sdata[i++] = crc[0];                       // CRCH
            sdata[i++] = crc[1];                       // CRCL

            OnSendUartData?.Invoke(addr, sdata, false, 1);
        }

        private void BtnGyroXAxisSet_Click(object sender, EventArgs e)
        {
            if (TeGyroXAxisNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeGyroXAxisNew.Text);
                wCalib = rCalib.DeepCopy();
                wCalib.AntiTheftGyro.XAxis = tmp;
                OnCommand?.Invoke(26, CALC_INDEX, 1, ref rParam, ref wCalib);
            }
        }

        private void BtnGyroYAxisSet_Click(object sender, EventArgs e)
        {
            if (TeGyroYAxisNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeGyroYAxisNew.Text);
                wCalib = rCalib.DeepCopy();
                wCalib.AntiTheftGyro.YAxis = tmp;
                OnCommand?.Invoke(27, CALC_INDEX, 1, ref rParam, ref wCalib);
            }
        }

        private void BtnGyroZAxisSet_Click(object sender, EventArgs e)
        {
            if (TeGyroZAxisNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeGyroZAxisNew.Text);
                wCalib = rCalib.DeepCopy();
                wCalib.AntiTheftGyro.ZAxis = tmp;
                OnCommand?.Invoke(28, CALC_INDEX, 1, ref rParam, ref wCalib);
            }
        }

        private void GyroScopeParamWrite(ushort waddr, int data)
        {
            byte[] crc;
            ushort raddr = 0x4000;
            int i = 0;
            // Normal mode --> Bootloader mode
            byte[] sdata = new byte[11 + 2 + 2];

            sdata[i++] = (byte)SystemId;                  // Device ID
            sdata[i++] = (byte)CsSerialCommFunctionDelta.READ_WRITE_REG;         // Command
            sdata[i++] = (byte)(raddr >> 8);                 // Read Register Address MSB
            sdata[i++] = (byte)(raddr >> 0);                 // Read Register Address LSB
            sdata[i++] = (byte)(7 >> 8);                    // Read Count of Register MSB
            sdata[i++] = (byte)(7 >> 0);                    // Read Count of Register LSB
            sdata[i++] = (byte)(waddr >> 8);       // Write Register Address MSB
            sdata[i++] = (byte)(waddr >> 0);       // Write Register Address LSB
            sdata[i++] = (byte)(1 >> 8);               // Write Count of Register MSB
            sdata[i++] = (byte)(1 >> 0);               // Write Count of Register LSB
            sdata[i++] = (byte)(1 * 2);                // Byte Count - [2 * (Num of register)]

            sdata[i++] = (byte)(data >> 8);
            sdata[i++] = (byte)(data >> 0);

            crc = CsSerialCommFunctionDelta.GetCRC(sdata, i);

            sdata[i++] = crc[1];                       // CRCH
            sdata[i++] = crc[0];                       // CRCL

            OnSendUartData?.Invoke((ushort)SystemId, sdata, false, 1);
        }

        private void AntiTheftCommParamWrite(ushort waddr, int data)
        {
            byte[] crc;
            ushort raddr = 0x3000;
            int i = 0;
            // Normal mode --> Bootloader mode
            byte[] sdata = new byte[11 + 2 + 2];

            sdata[i++] = (byte)SystemId;                  // Device ID
            sdata[i++] = (byte)CsSerialCommFunctionDelta.READ_WRITE_REG;         // Command
            sdata[i++] = (byte)(raddr >> 8);                 // Read Register Address MSB
            sdata[i++] = (byte)(raddr >> 0);                 // Read Register Address LSB
            sdata[i++] = (byte)(3 >> 8);                    // Read Count of Register MSB
            sdata[i++] = (byte)(3 >> 0);                    // Read Count of Register LSB
            sdata[i++] = (byte)(waddr >> 8);       // Write Register Address MSB
            sdata[i++] = (byte)(waddr >> 0);       // Write Register Address LSB
            sdata[i++] = (byte)(1 >> 8);               // Write Count of Register MSB
            sdata[i++] = (byte)(1 >> 0);               // Write Count of Register LSB
            sdata[i++] = (byte)(1 * 2);                // Byte Count - [2 * (Num of register)]

            sdata[i++] = (byte)(data >> 8);
            sdata[i++] = (byte)(data >> 0);

            crc = CsSerialCommFunctionDelta.GetCRC(sdata, i);

            sdata[i++] = crc[1];                       // CRCH
            sdata[i++] = crc[0];                       // CRCL

            OnSendUartData?.Invoke((ushort)SystemId, sdata, false, 1);
        }

        private void BtnGyroPolSel_Click(object sender, EventArgs e)
        {
            if (TeGyroPolSelNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeGyroPolSelNew.Text);
                GyroScopeParamWrite(0x4003, tmp);
            }
        }

        private void BtnFuncSw_Click(object sender, EventArgs e)
        {
            if (TeGyroFunctionSwitchNew.Text != "")
            {
                int tmp = Convert.ToInt32(TeGyroFunctionSwitchNew.Text);
                GyroScopeParamWrite(0x4004, tmp);
            }
        }

        private void BtnGyroState_Click(object sender, EventArgs e)
        {
        }
        #endregion

        #region TIMER EVENT
        private void TmrDisplay_Tick(object sender, EventArgs e)
        {
            DisplayAntiTheft();
        }
        #endregion
    }
}
