using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

using DevExpress.XtraCharts;
using LFP_Manager.DataStructure;

namespace LFP_Manager.Controls
{
    public delegate void CommandEvent(int sId, int cmd, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib);

    public partial class ucMainStatus : DevExpress.XtraEditors.XtraUserControl
    {
        #region VARIABLES

        private CommConfig Config;
        private DeviceSystemTotalData SystemTotalData;
        private DeviceSystemData[] SystemData;

        private ucModuleMainHeader ModuleMainHeader;
        private ucModuleMainB[] ModuleMain;
        private DevExpress.XtraLayout.LayoutControlItem[] lcitemModuleMain;
        private DevExpress.XtraLayout.EmptySpaceItem[] emptySpaceItem;

        private int mQty;

        private double TotalVoltage;
        private double TotalCurrent;
        private double TotalTemperature;
        private double TotalSoc;
        private double TotalSoh;

        private bool active = false;

        public event CommandEvent OnCommand = null;

        #endregion

        #region CONSTRUCTORS

        public ucMainStatus()
        {
            InitializeComponent();

            mQty = csConstData.SystemInfo.MAX_MODULE_SIZE;
        }

        #endregion

        public void UpdateMainConfig(ref CommConfig aConfig, ref DeviceSystemData[] mSystemData)
        {
            Config = aConfig;
            SystemData = mSystemData;

            mQty = Config.ModuleQty;

            LoadModuleMain(mQty);

            lcgbModuleMain.Invalidate();
        }

        private void LoadModuleMain(int mQty)
        {
            lcModuleMain.Controls.Clear();
            lcgbModuleMain.Items.Clear();

            ModuleMainHeader = new ucModuleMainHeader();
            ModuleMain = new ucModuleMainB[mQty];
            lcitemModuleMain = new DevExpress.XtraLayout.LayoutControlItem[mQty + 1];

            int empsize = csConstData.SystemInfo.MAX_MODULE_SIZE - mQty;

            if (empsize > 0)
            {
                emptySpaceItem = new DevExpress.XtraLayout.EmptySpaceItem[empsize];
            }

            int tWidth = lcgbModuleMain.Size.Width;
            int tHeight = lcgbModuleMain.Size.Height;

            lcitemModuleMain[0] = new DevExpress.XtraLayout.LayoutControlItem
            {
                Control = ModuleMainHeader,
                Name = String.Format("lcitemModuleMainHeader"),
                Size = new Size(tWidth - 4, 30),
                Location = new Point(2, 2),
                TextVisible = false,
                Padding = new DevExpress.XtraLayout.Utils.Padding(0, 0, 0, 0)
            };

            int emp = 0;
            for (int i = 0; i < csConstData.SystemInfo.MAX_MODULE_SIZE; i++)
            {
                if (i < mQty)
                {
                    ModuleMain[i] = new ucModuleMainB(Config, i + 1, ref SystemData[i]);
                    ModuleMain[i].OnCommand += SetCmdEvent;

                    lcitemModuleMain[i + 1] = new DevExpress.XtraLayout.LayoutControlItem
                    {
                        Control = ModuleMain[i],
                        Name = String.Format("lcitemModuleMain_{0}", i + 1),
                        Size = new Size(tWidth - 4, 60),
                        Location = new Point(2, 2 + 30 + (i * 60)),
                        TextVisible = false,
                        Padding = new DevExpress.XtraLayout.Utils.Padding(0, 0, 0, 0)
                    };
                }
                else
                {
                    emptySpaceItem[emp] = new DevExpress.XtraLayout.EmptySpaceItem
                    {
                        Size = new Size(tWidth - 4, 60),
                        Location = new Point(2, 2 + 30 + (i * 60))
                    };
                    emp++;
                }
            }

            lcModuleMain.Controls.Add(ModuleMainHeader);
            for (int i = 0; i < csConstData.SystemInfo.MAX_MODULE_SIZE; i++)
            {
                if (i < mQty)
                    lcModuleMain.Controls.Add(ModuleMain[i]);
            }

            DevExpress.XtraLayout.BaseLayoutItem[] abase = new DevExpress.XtraLayout.BaseLayoutItem[csConstData.SystemInfo.MAX_MODULE_SIZE + 1];

            emp = 0;
            for (int i = 0; i < csConstData.SystemInfo.MAX_MODULE_SIZE + 1; i++)
            {
                if (i < (mQty + 1))
                    abase[i] = lcitemModuleMain[i];
                else
                    abase[i] = emptySpaceItem[emp++];
            }

            lcgbModuleMain.Items.AddRange(abase);
            
            lcgbModuleMain.Invalidate();
        }

        public void Start(ref CommConfig aConfig, ref DeviceSystemTotalData aSystemTotalData, ref DeviceSystemData[] aSystemData)
        {
            Config = aConfig;
            SystemTotalData = aSystemTotalData;
            SystemData = aSystemData;

            switch (Config.CommType)
            {
                case csConstData.CommType.COMM_UART_MULTI:
                    mQty = Config.ModuleQty;
                    break;
                default:
                    mQty = Config.ModuleQty;
                    break;
            }
            active = true;
            tmrDisplay.Enabled = true;
        }

        public void Stop()
        {
            active = false;
            tmrDisplay.Enabled = false;
        }

        public void UpdateData(ref DeviceSystemTotalData aSystemTotalData, ref DeviceSystemData[] aSystemData)
        {
            if (active)
            {
                SystemTotalData = aSystemTotalData;
                SystemData = aSystemData;

                //if (this.InvokeRequired)
                //{
                //    this.Invoke(new MethodInvoker(delegate ()
                //    {
                //        //mQty = SystemTotalData.IdentData.ModuleQuantity;
                //        LoadModuleMain(mQty);

                //        OnCommand?.Invoke(0, 1, mQty, 1, ref Param, ref Calib);
                //    }));
                //}
                //else
                //{
                //    //mQty = SystemTotalData.IdentData.ModuleQuantity;
                //    LoadModuleMain(mQty);

                //    OnCommand?.Invoke(0, 1, mQty, 1, ref Param, ref Calib);
                //}

                TotalVoltage = (double)SystemTotalData.ValueData.TotalVoltage / 10;
                TotalCurrent = (double)SystemTotalData.ValueData.TotalCurrent / 10;
                TotalSoc = (double)SystemTotalData.ValueData.TotalSOC / 10;
                TotalSoh = (double)SystemTotalData.ValueData.TotalSOH / 10;
                TotalTemperature = (double)SystemTotalData.ValueData.TotalTemp / 10;

                for (int i = 0; i < ModuleMain.Length; i++)
                {
                    ModuleMain[i].UpdateData(ref SystemData[i]);
                }
            }
        }
        #region ON EVENT FUNCTION

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

        #endregion

        #region BUTTON EVENT

        #endregion

        #region TIMER EVENT
        private void tmrDisplay_Tick(object sender, EventArgs e)
        {
            DisplayTotalValue();
            DisplayStatusAndAlarm();
        }

        #endregion

        #region DISPLAY FUNCTION
        private void DisplayTotalValue()
        {
            if (active)
            {
                rtGraph.Text = String.Format("Real Time Graph - {0} - {1} Modules"
                                            , String.Format("V{0}", SystemTotalData.IdentData.FwVerStr)
                                            , Config.ModuleQty);

                dgTotalVoltage.Text = String.Format("{0:0.0}", TotalVoltage);
                dgTotalCurrent.Text = String.Format("{0:0.0}", TotalCurrent);
                dgTotalTemp.Text = String.Format("{0:0.0}", TotalTemperature);
                dgTotalSOC.Text = String.Format("{0:0.0}", TotalSoc);
                dgTotalSOH.Text = String.Format("{0:0.0}", TotalSoh);

                chartVI.Invalidate();
            }
        }

        private void DisplayStatusAndAlarm()
        {
            if (SystemTotalData.CommFail == false)
            {
                // Operating Status
                if (SystemTotalData.StatusData.status == 0)
                {
                    lbStatus.Text = "STANDBY";
                    lbStatus.ForeColor = System.Drawing.Color.Black;
                }
                else if (SystemTotalData.StatusData.status == 1)
                {
                    lbStatus.Text = "CHARGING";
                    lbStatus.ForeColor = System.Drawing.Color.Blue;
                }
                else if (SystemTotalData.StatusData.status == 2)
                {
                    lbStatus.Text = "DISCHARGING";
                    lbStatus.ForeColor = System.Drawing.Color.Magenta;
                }
                else if (SystemTotalData.StatusData.status == 3)
                {
                    lbStatus.Text = "FLOATING";
                    lbStatus.ForeColor = System.Drawing.Color.Black;
                }
                else
                {
                    lbStatus.Text = "UNKNOWN";
                    lbStatus.ForeColor = System.Drawing.Color.Black;
                }
                // Alarm Display
                switch (SystemTotalData.StatusData.batteryStatus)
                {
                    case 0:         // NORMAL
                        lbAlarm.Text = "NORMAL";
                        lbAlarm.ForeColor = System.Drawing.Color.Green;
                        break;
                    case 1:         // WARNING
                        lbAlarm.Text = "NORMAL";
                        lbAlarm.ForeColor = System.Drawing.Color.Green;
                        break;
                    case 2:         // FAULT
                        lbAlarm.Text = "NORMAL";
                        lbAlarm.ForeColor = System.Drawing.Color.Green;
                        break;
                    case 3:         // WARMING UP
                        lbAlarm.Text = "WARMING UP";
                        lbAlarm.ForeColor = System.Drawing.Color.Green;
                        break;
                    case 4:         // FAULT (Anti-Theft Comm.)
                        lbAlarm.Text = "FAULT (Anti-Theft)";
                        lbAlarm.ForeColor = System.Drawing.Color.Green;
                        break;
                    case 5:         // FAULT (Anti-Theft Gyro-Scope)
                        lbAlarm.Text = "FAULT (Anti-Theft)";
                        lbAlarm.ForeColor = System.Drawing.Color.Green;
                        break;
                    default:
                        lbAlarm.Text = string.Format("UNKNOWN ({0})", SystemTotalData.StatusData.batteryStatus);
                        lbAlarm.ForeColor = System.Drawing.Color.Red;
                        break;
                }
            }
            else
            {
                lbStatus.Text = "OFF-LINE";
                lbStatus.ForeColor = System.Drawing.Color.Red;
                lbAlarm.Text = "OFF-LINE";
                lbAlarm.ForeColor = System.Drawing.Color.Red;
            }
        }

        #endregion
    }
}
