using LFP_Manager.DataStructure;
using LFP_Manager.Function;
using System;
using System.Data;
using System.Windows.Forms;

namespace LFP_Manager.Forms
{
    public partial class fmxHistory : DevExpress.XtraEditors.XtraForm
    {
        #region VARIABLES

        private int SystemId = 0;
        private CommConfig Config;

        private byte[] rData = null;
        private ushort curr_addr = 0;
        private int hist_no = 0;
        private bool stopReq = true;

        private DateTime ReqDateTime;

        private DataTable BmsHistoryTable = null;

        public event SendDataUartEvent OnSendUartData = null;

        #endregion

        #region CONTRUCTORS

        //public fmxHistory()
        //{
        //    InitializeComponent();
        //}

        public fmxHistory(CommConfig aConfig, int systemId)
        {
            InitializeComponent();

            Config = aConfig;

            ucHistroy1.SetCommCofig(Config);
            SystemId = systemId;

            CreateHistoryColomn(ref BmsHistoryTable);

            switch (Config.CommType)
            {
                case csConstData.CommType.COMM_UART:
                    pgBmsHistory.PageEnabled = true;
                    //tabHistory.TabPages.Remove(pgBmsHistory);
                    break;
                case csConstData.CommType.COMM_RS485:
                    pgBmsHistory.PageEnabled = false;
                    tabHistory.TabPages.Remove(pgBmsHistory);
                    break;
                case csConstData.CommType.COMM_SNMP:
                    pgBmsHistory.PageEnabled = false;
                    tabHistory.TabPages.Remove(pgBmsHistory);
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region INITIALIZE COMPONENT

        private void CreateHistoryColomn(ref DataTable hDT)
        {
            hDT = new DataTable();

            hDT.Columns.Add("no", typeof(int));
            hDT.Columns.Add("datetime", typeof(DateTime));
            hDT.Columns.Add("status", typeof(int));
            hDT.Columns.Add("warning", typeof(string));
            hDT.Columns.Add("protect", typeof(string));
            hDT.Columns.Add("error", typeof(string));

            hDT.Columns.Add("voltage", typeof(float));
            hDT.Columns.Add("current", typeof(float));
            hDT.Columns.Add("SOC", typeof(float));
            hDT.Columns.Add("SOH", typeof(float));

            for (int i = 0; i < 6; i++)
            {
                hDT.Columns.Add(string.Format("temp_{0:00}", i + 1), typeof(float));
            }
            for (int i = 0; i < 16; i++)
            {
                hDT.Columns.Add(string.Format("cell_v_{0:00}", i + 1), typeof(float));
            }
            gcBmsHistory.DataSource = hDT;
        }

        #endregion

        #region PUBLIC FUNCTIONS
        private short[] ByteArrTo2Short(byte[] bytes)
        {
            short[] result = null;

            if (bytes != null)
            {
                int len = bytes[2];
                result = new short[len / 2];

                for (int i = 0; i < result.Length; i++)
                {
                    result[i] = (short)((bytes[3 + (i * 2) + 0] << 8) + bytes[3 + (i * 2) + 1]);
                }
            }
            return result;
        }
        public void RecvUardData(byte[] data)
        {
            rData = data;

            if ((rData != null) && (rData.Length > 58))
            {
                try
                {
                    DataRow hRow = BmsHistoryTable.NewRow();

                    short[] shorts = ByteArrTo2Short(data);

                    int pos = 0;
                    int yy, MM, dd, HH, mm, ss;
                    Int32 iDateTime = (rData[3 + 2] << 24) | (rData[3 + 3] << 16) | (rData[3 + 0] << 8) | (rData[3 + 1] << 0);
                    //Int32 iDateTime = (Int32)((shorts[pos + 1] << 16) | (shorts[pos + 0] << 0));
                    yy = (iDateTime >> 26) & 0x003F;
                    MM = (iDateTime >> 22) & 0x000F;
                    dd = (iDateTime >> 17) & 0x001F;
                    HH = (iDateTime >> 12) & 0x001F;
                    mm = (iDateTime >> 6) & 0x003F;
                    ss = (iDateTime >> 0) & 0x003F;

                    hRow["no"] = hist_no;
                    string stDateTime = string.Format("{0}-{1:00}-{2:00} {3:00}:{4:00}:{5:00}"
                        , yy
                        , MM
                        , dd
                        , HH
                        , mm
                        , ss
                        );

                    DateTime aDateTime = Convert.ToDateTime(stDateTime);
                    hRow["datetime"] = aDateTime;

                    pos = 2;
                    hRow["status"] = shorts[pos++];
                    hRow["warning"] = string.Format("{0:X4}", shorts[pos++]);
                    hRow["protect"] = string.Format("{0:X4}", shorts[pos++]);
                    hRow["error"] = string.Format("{0:X4}", shorts[pos++]);
                    hRow["voltage"] = string.Format("{0:0.00}", Convert.ToDouble(shorts[pos++]) / 100);
                    hRow["current"] = string.Format("{0:0.00}", Convert.ToDouble(shorts[pos++]) / 100);
                    hRow["SOC"] = string.Format("{0:0.0}", Convert.ToDouble(shorts[pos++]) / 1);

                    // Temperature
                    for (int i = 0; i < 3; i++)
                    {
                        hRow[string.Format("temp_{0:00}", (i * 2) + 1)] = Convert.ToDouble((byte)(shorts[pos] >> 8));
                        hRow[string.Format("temp_{0:00}", (i * 2) + 2)] = Convert.ToDouble((byte)(shorts[pos++] >> 0));
                    }
                    // Cell Voltage
                    for (int i = 0; i < 16; i++)
                    {
                        hRow[string.Format("cell_v_{0:00}", i + 1)] = Convert.ToDouble(shorts[pos++]) / 1000;
                    }
                    hRow["SOH"] = string.Format("{0:0.0}", Convert.ToDouble(shorts[pos++]) / 1);

                    BmsHistoryTable.Rows.Add(hRow);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                }
            }
            gvBmsHistory.BestFitColumns();
            gvBmsHistory.ClearSelection();

            hist_no++;
            curr_addr += 0x20;
            RequestHistoryData(curr_addr);
        }

        #endregion

        #region BUTTON EVENT

        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnBmsHistoryReq_Click(object sender, EventArgs e)
        {
            if (stopReq)
            {
                BmsHistoryTable.Rows.Clear();

                stopReq = false;
                hist_no = 1;
                curr_addr = 0x0200;
                TmrCheckReq.Enabled = true;

                RequestHistoryData(curr_addr);

                btnBmsHistoryReq.Text = "STOP";
            }
            else
            {
                stopReq = true;
                //btnBmsHistoryReq.Text = "Request";
                //TmrCheckReq.Enabled = false;
            }
        }

        private void RequestHistoryData(ushort haddr)
        {
            byte[] crc;
            ushort addr = haddr;

            // Normal mode --> Bootloader mode
            byte[] sdata = new byte[8];
            sdata[0] = (byte)SystemId;         // Dev Address
            sdata[1] = 0x03;         // Function Code
            sdata[2] = (byte)(addr >> 8);         // Address H
            sdata[3] = (byte)(addr >> 0);         // Address L
            sdata[4] = 0x00;         // Number of Register H
            sdata[5] = 0x1D;         // Number of Register L

            crc = csSerialCommFunction.GetCRC(sdata, 6);

            sdata[6] = crc[1];         // CRCH
            sdata[7] = crc[0];         // CRCL

            if (stopReq == false)
            {
                OnSendUartData?.Invoke(addr, sdata, false, 1);
                ReqDateTime = DateTime.Now;
            }
        }

        private void btnExportExcel_Click(object sender, EventArgs e)
        {
            SaveFileDialog sDialog = new SaveFileDialog();
            sDialog.Title = "Select save file";
            sDialog.DefaultExt = "xlsx";
            sDialog.Filter = "Excel files 2003 (*.xls)|*.xls|All files (*.*)|*.*";

            if (sDialog.ShowDialog() == DialogResult.OK)
            {
                string filename = sDialog.FileName;

                try
                {
                    csExcelExport.ExportToExcelExt(BmsHistoryTable, filename);

                    MessageBox.Show("Complete Export Excel File", "Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        #endregion

        #region GRID DISPLAY
        private void gvBmsHistory_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
        {
            if (e.Column.FieldName == "status")
            {
                int status = Convert.ToInt32(e.Value);
                switch (status)
                {
                    case 0:
                        e.DisplayText = "Standby";
                        break;
                    case 1:
                        e.DisplayText = "Charging";
                        break;
                    case 2:
                        e.DisplayText = "Discharging";
                        break;
                    case 4:
                        e.DisplayText = "Protect";
                        break;
                    case 8:
                        e.DisplayText = "Charging-Lmt";
                        break;
                    case 0x32:
                        e.DisplayText = "Power-On";
                        break;
                    default:
                        e.DisplayText = string.Format("Unknown({0:X4})", status);
                        break;
                }
            }
        }
        #endregion

        #region TIMER EVENT
        private void TmrCheckReq_Tick(object sender, EventArgs e)
        {
            DateTime nDateTime = ReqDateTime.AddSeconds(1);

            if (nDateTime < DateTime.Now)
            {
                TmrCheckReq.Enabled = false;

                MessageBox.Show("Finished BMS History Read", "Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
                btnBmsHistoryReq.Text = "Request";
            }
        }
        #endregion
    }
}
