using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraEditors;

using LFP_Manager.Forms;
using LFP_Manager.Controls;
using LFP_Manager.DataStructure;
using LFP_Manager.Function;
using LFP_Manager.Threads;
using LFP_Manager.Utils;
using DevExpress.Utils.Drawing.Helpers;
using System.Threading.Tasks;

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

        // Child form
        private fmxInventoryConfig InventoryConfig = null;
        private fmxModuleDetail ModuleDetailForm = null;
        private fmxFwUpdate FwUpdateForm = null;
        private fmxHistory HistoryForm = null;

        // Static Variables
        private CommConfig Config = new CommConfig();
        private DeviceSystemTotalData SystemTotalData;
        private DeviceSystemData[] SystemData;

        // Thread Variables
        private csUartThread uartThread = null;
        private CsUartThread124050 rs232Thread124050 = null;
        private CsUartThreadDelta rs485Thread = null;
        private CsRs485Thread124050 rs485Thread124050 = null;
        private CsSnmpThread snmpThread = null;
        private CsSnmpThread124050 snmpThread124050 = null;

        private csDbThread dbThread = null;

        private ucMainStatus MainStatus = null;
        private ucShelfStatus ShelfStatus = null;

        private int ModuleID = 1;

        bool Active = false;

        #endregion

        #region CONSTRUCTORS

        public fmxMain()
        {
            InitializeComponent();

            StructDataInit();
            //DataInit();

            IniLoad(ref Config);

            uTarget.OnConfig += ConfigButtonClick;
            uTarget.OnStart += StartButtonClick;

            uDataLog.OnUpdate += LogStatusUpdate;

            DisplaySystemFwVerModule();
        }

        private void IniLoad(ref CommConfig aConfig)
        {
            csIniControlFunction.IniLoad(Application.ExecutablePath, ref aConfig);

            uTarget.UpdateConfig(ref aConfig);

            TypeChangedUpdate(ref aConfig);
        }

        private void StructDataInit()
        {
            SystemTotalData = new DeviceSystemTotalData
            {
                ValueData = new DeviceValueTotalData(),
                StatusData = new DeviceStatusTotalData()
            };

            SystemData = new DeviceSystemData[csConstData.SystemInfo.MAX_MODULE_SIZE];

            for (int i = 0; i < csConstData.SystemInfo.MAX_MODULE_SIZE; i++)
            {
                SystemData[i] = new DeviceSystemData();
            }
        }

        #endregion

        #region BUTTON EVENT

        private void ConfigButtonClick(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxCommConfig")
                {
                    frm.Activate();
                    return;
                }
            }
            fmxCommConfig CommConfigForm = new fmxCommConfig
            {
                Owner = this
            };

            CommConfigForm.OnUpdate += UpdateConfig;
            CommConfigForm.Show();
        }

        private void StartButtonClick(object sender, EventArgs e)
        {
            if (Active)
            {
                StructDataInit();

                switch (Config.CommType)
                {
                    case csConstData.CommType.COMM_UART:
                        switch (Config.UartModelIndex)
                        {
                            case csConstData.MODEL_INDEX.LFPM_124050D:     // AMG Protocol
                                if (rs232Thread124050 != null)
                                {
                                    rs232Thread124050.disposeThread();
                                    rs232Thread124050 = null;
                                    UpdateDataUart(this, ref SystemData[ModuleID - 1]);

                                    edModuleID.Enabled = true;
                                    chbPolling.Enabled = true;
                                }
                                break;
                            default:
                                if (uartThread != null)
                                {
                                    uartThread.disposeThread();
                                    uartThread = null;
                                    UpdateDataUart(this, ref SystemData[ModuleID - 1]);

                                    edModuleID.Enabled = true;
                                    chbPolling.Enabled = true;
                                }
                                break;
                        }
                        break;
                    case csConstData.CommType.COMM_RS485:
                        // DELTA Protocol
                        switch (Config.UartModelIndex)
                        {
                            case csConstData.MODEL_INDEX.LFPM_124050D:
                                if (rs485Thread124050 != null)
                                {
                                    rs485Thread124050.disposeThread();
                                    rs485Thread124050 = null;
                                    UpdateDataRS485(this, ref SystemData);

                                    edModuleID.Enabled = true;
                                    chbPolling.Enabled = true;
                                }
                                break;
                            default:
                                if (rs485Thread != null)
                                {
                                    rs485Thread.disposeThread();
                                    rs485Thread = null;
                                    UpdateDataRS485(this, ref SystemData);

                                    edModuleID.Enabled = true;
                                    chbPolling.Enabled = true;
                                }
                                break;
                        }    
                        break;
                    case csConstData.CommType.COMM_SNMP:
                        break;
                    default:
                        break;
                }

                if (snmpThread != null)
                {
                    snmpThread.disposeThread();
                    snmpThread = null;
                    UpdateSnmpData(this, ref SystemData[0]);
                }

                if (snmpThread124050 != null)
                {
                    snmpThread124050.Dispose();
                    snmpThread124050 = null;
                    UpdateSnmpData(this, ref SystemData[0]);
                }

                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }

                Active = false;
            }
            else
            {
                try
                {
                    ModuleID = Convert.ToInt16(edModuleID.Text);
                }
                catch (Exception)
                {
                    MessageBox.Show("Wrong Module ID - Please check module ID", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                switch (Config.CommType)
                {
                    case csConstData.CommType.COMM_UART:
                        // UART MODE - RS-232
                        switch (Config.UartModelIndex)
                        {
                            case csConstData.MODEL_INDEX.LFPM_124050D:
                                CommUARTStart124050();
                                break;
                            default:
                                CommUARTStart();
                                break;
                        }
                        break;
                    case csConstData.CommType.COMM_RS485:
                        // UART MODE - RS-485
                        switch (Config.UartModelIndex)
                        {
                            case csConstData.MODEL_INDEX.LFPM_124050D:
                                CommRS485_124050_Start();
                                break;
                            default:
                                CommRS485Start();
                                break;
                        }
                        break;
                    case csConstData.CommType.COMM_SNMP:
                        switch (Config.SnmpModelIndex)
                        {
                            case csConstData.MODEL_INDEX.LFPM_124050D:
                                StartProcessSNMP124050();
                                break;
                            default:
                                StartProcessSNMP();
                                break;
                        }
                        break;
                }
            }
            uTarget.UpdateStatus(Active);
            uDataLog.UpdateActiveStatus(Active, ModuleID, Config, SystemData);
            DisplayCommStatus();
        }

        private void UartRecvData(byte[] data)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate ()
                {
                    FwUpdateForm?.RecvData(data);
                    HistoryForm?.RecvUardData(data);
                }));
            }
            else
            {
                FwUpdateForm?.RecvData(data);
                HistoryForm?.RecvUardData(data);
            }
        }

        private void CommUARTStart()
        {
            try
            {
                uartThread = new csUartThread(ModuleID, Config, ref SystemData[ModuleID - 1]);
                uartThread.OnUpdate += UpdateDataUart;
                uartThread.OnDataRecv += UartRecvData;
                uartThread.OnPrint += CommDataPrint;
                uartThread.SetPolling(chbPolling.Checked, ModuleID, ref SystemData[ModuleID - 1]);

                if (uartThread.Start(ref Config, ModuleID, chbPolling.Checked))
                {
                    Active = true;
                    edModuleID.Enabled = false;
                    chbPolling.Enabled = true;

                    if (chbPolling.Checked)
                        edModuleID.Enabled = false;
                    else
                        edModuleID.Enabled = true;

                    uartThread.SetPolling(chbPolling.Checked, ModuleID, ref SystemData[ModuleID - 1]);
                    ShelfStatus?.UpdateSystemId(ModuleID);

                    dbThread = new csDbThread(ModuleID, Config, SystemData);
                    dbThread.Start(ModuleID, Config);
                }
                else
                {
                    if (uartThread != null)
                    {
                        uartThread.disposeThread();
                        uartThread = null;
                    }
                    if (dbThread != null)
                    {
                        dbThread.disposeThread();
                        dbThread = null;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                if (uartThread != null)
                {
                    uartThread.disposeThread();
                    uartThread = null;
                }
                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }
            }
        }
        private void CommUARTStart124050()
        {
            try
            {
                rs232Thread124050 = new CsUartThread124050(ModuleID, Config, ref SystemData[ModuleID - 1]);
                rs232Thread124050.OnUpdate += UpdateDataUart;
                rs232Thread124050.OnDataRecv += UartRecvData;
                rs232Thread124050.OnPrint += CommDataPrint;
                rs232Thread124050.SetPolling(chbPolling.Checked, ModuleID, ref SystemData[ModuleID - 1]);

                if (rs232Thread124050.Start(ref Config, ModuleID, chbPolling.Checked))
                {
                    // UI 스레드에서 실행 보장
                    this.Invoke((Action)(() =>
                    {
                        Active = true;
                        edModuleID.Enabled = false;
                        chbPolling.Enabled = true;

                        edModuleID.Enabled = !chbPolling.Checked;

                        rs232Thread124050.SetPolling(chbPolling.Checked, ModuleID, ref SystemData[ModuleID - 1]);
                        ShelfStatus?.UpdateSystemId(ModuleID);

                        dbThread = new csDbThread(ModuleID, Config, SystemData);
                        dbThread.Start(ModuleID, Config);
                    }));
                }
                else
                {
                    if (rs232Thread124050 != null)
                    {
                        rs232Thread124050.disposeThread();
                        rs232Thread124050 = null;
                    }
                    if (dbThread != null)
                    {
                        dbThread.disposeThread();
                        dbThread = null;
                    }
                }
            }
            catch (Exception ex)
            {
                Active = false;

                if (rs232Thread124050 != null)
                {
                    rs232Thread124050.disposeThread();
                    rs232Thread124050 = null;
                }
                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }

                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CommRS485Start()
        {
            try
            {
                rs485Thread = new CsUartThreadDelta(ModuleID, Config, ref SystemData);
                rs485Thread.OnUpdate += UpdateDataRS485;
                rs485Thread.OnDataRecv += UartRecvData;
                rs485Thread.OnPrint += CommDataPrint;
                rs485Thread.SetPolling(chbPolling.Checked, ModuleID, ref SystemData);

                if (rs485Thread.Start(ref Config, ModuleID, chbPolling.Checked))
                {
                    Active = true;
                    edModuleID.Enabled = false;
                    chbPolling.Enabled = true;

                    edModuleID.Enabled = !chbPolling.Checked;

                    rs485Thread.SetPolling(chbPolling.Checked, ModuleID, ref SystemData);
                    ShelfStatus?.UpdateSystemId(ModuleID);

                    dbThread = new csDbThread(ModuleID, Config, SystemData);
                    dbThread.Start(ModuleID, Config);
                }
                else
                {
                    if (rs485Thread != null)
                    {
                        rs485Thread.disposeThread();
                        rs485Thread = null;
                    }
                    if (dbThread != null)
                    {
                        dbThread.disposeThread();
                        dbThread = null;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                if (rs485Thread != null)
                {
                    rs485Thread.disposeThread();
                    rs485Thread = null;
                }
                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }
            }
        }

        private void CommRS485_124050_Start()
        {
            try
            {
                rs485Thread124050 = new CsRs485Thread124050(ModuleID, Config, ref SystemData);
                rs485Thread124050.OnUpdate += UpdateDataRS485;
                rs485Thread124050.OnDataRecv += UartRecvData;
                rs485Thread124050.OnPrint += CommDataPrint;
                rs485Thread124050.SetPolling(chbPolling.Checked, ModuleID, ref SystemData);

                if (rs485Thread124050.Start(ref Config, ModuleID, chbPolling.Checked))
                {
                    Active = true;
                    edModuleID.Enabled = false;
                    chbPolling.Enabled = true;

                    edModuleID.Enabled = !chbPolling.Checked;

                    rs485Thread124050.SetPolling(chbPolling.Checked, ModuleID, ref SystemData);
                    ShelfStatus?.UpdateSystemId(ModuleID);

                    dbThread = new csDbThread(ModuleID, Config, SystemData);
                    dbThread.Start(ModuleID, Config);
                }
                else
                {
                    if (rs485Thread124050 != null)
                    {
                        rs485Thread124050.disposeThread();
                        rs485Thread124050 = null;
                    }
                    if (dbThread != null)
                    {
                        dbThread.disposeThread();
                        dbThread = null;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                if (rs485Thread124050 != null)
                {
                    rs485Thread124050.disposeThread();
                    rs485Thread124050 = null;
                }
                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }
            }
        }

        private void StartProcessSNMP()
        {
            try
            {
                snmpThread = new CsSnmpThread(Config, ref SystemData[ModuleID - 1]);
                snmpThread.OnUpdate += UpdateSnmpData;
                snmpThread.OnSetResult += SnmpRecvData;
                snmpThread.Start(Config.SnmpIP, chbPolling.Checked);

                Active = true;

                dbThread = new csDbThread(ModuleID, Config, SystemData);
                dbThread.Start(ModuleID, Config);
            }
            catch (Exception)
            {
                if (snmpThread == null)
                {
                    snmpThread.disposeThread();
                    snmpThread = null;
                }
                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }
            }
        }
        private void StartProcessSNMP124050()
        {
            try
            {
                snmpThread124050 = new CsSnmpThread124050(Config, ref SystemData[ModuleID - 1]);
                snmpThread124050.OnUpdate += UpdateSnmpData;
                snmpThread124050.OnSetResult += SnmpRecvData;
                snmpThread124050.Start(Config.SnmpIP, chbPolling.Checked);

                Active = true;

                dbThread = new csDbThread(ModuleID, Config, SystemData);
                dbThread.Start(ModuleID, Config);
            }
            catch (Exception)
            {
                if (snmpThread124050 == null)
                {
                    snmpThread124050.Dispose();
                    snmpThread124050 = null;
                }
                if (dbThread != null)
                {
                    dbThread.disposeThread();
                    dbThread = null;
                }
            }
        }

        #endregion

        #region UPDATE FUNCTIONS

        private void TypeChangeUpdateUart(ref CommConfig aConfig)
        {
            tabStatus.TabPages[0].PageVisible = true;
            for (int i = 1; i < tabStatus.TabPages.Count; i++)
            {
                tabStatus.TabPages[i].PageVisible = false;
            }
            tabStatus.TabPages[0].Text = String.Format("LFP Module [{0}.{1}.{2}.{3}]"
                , 0
                , 0
                , 0
                , 0
                );
            ShelfStatus = new ucShelfStatus();
            ShelfStatus.OnCommand += SetCmdEvent;
            ShelfStatus.Dock = DockStyle.Fill;

            tabStatus.TabPages[0].PageVisible = true;
            tabStatus.TabPages[0].Controls.Add(ShelfStatus);

            ShelfStatus.Start(Convert.ToInt32(edModuleID.Text), ref aConfig, ref SystemData);

            edModuleID.Enabled = true;
            chbPolling.Enabled = true;
        }
        private void TypeChangeUpdateRS485(ref CommConfig aConfig)
        {
            // Display Screen Delete
            if (MainStatus != null)
            {
                MainStatus.Dispose();
                MainStatus = null;
            }

            if (ShelfStatus != null)
            {
                ShelfStatus.Dispose();
                ShelfStatus = null;
            }
            if (aConfig.ModuleQty > 1)
            {
                // All disable first
                for (int i = 0; i < tabStatus.TabPages.Count; i++)
                {
                    tabStatus.TabPages[i].PageVisible = false;
                }

                MainStatus = new ucMainStatus();
                MainStatus.OnCommand += SetCmdEvent;

                tabStatus.TabPages[0].Text = string.Format("LFP System");
                tabStatus.TabPages[0].PageVisible = true;
                tabStatus.TabPages[0].Controls.Add(MainStatus);
                MainStatus.Dock = DockStyle.Fill;
                MainStatus.UpdateMainConfig(ref Config, ref SystemData);

                //SystemTotalData.IdentData.ModuleQuantity = Config.ModuleQty;

                edModuleID.Enabled = false;
                chbPolling.Enabled = false;
            }
            else
            {
                tabStatus.TabPages[0].PageVisible = true;
                for (int i = 1; i < tabStatus.TabPages.Count; i++)
                {
                    tabStatus.TabPages[i].PageVisible = false;
                }
                tabStatus.TabPages[0].Text = String.Format("LFP Module [{0}.{1}.{2}.{3}]"
                    , 0
                    , 0
                    , 0
                    , 0
                    );
                ShelfStatus = new ucShelfStatus();
                ShelfStatus.OnCommand += SetCmdEvent;
                ShelfStatus.OnSendUartData += SetWriteData;
                ShelfStatus.Dock = DockStyle.Fill;

                tabStatus.TabPages[0].PageVisible = true;
                tabStatus.TabPages[0].Controls.Add(ShelfStatus);

                ShelfStatus.Start(ModuleID, ref aConfig, ref SystemData);

                edModuleID.Enabled = true;
                chbPolling.Enabled = true;
            }
        }
        private void TypeChangeUpdateSnmp(ref CommConfig aConfig)
        {
            tabStatus.TabPages[0].PageVisible = true;
            for (int i = 1; i < tabStatus.TabPages.Count; i++)
            {
                tabStatus.TabPages[i].PageVisible = false;
            }
            tabStatus.TabPages[0].Text = String.Format("LFP Module [{0}.{1}.{2}.{3}]"
                , 0
                , 0
                , 0
                , 0
                );
            ShelfStatus = new ucShelfStatus();
            ShelfStatus.OnCommand += SetCmdEvent;
            ShelfStatus.Dock = DockStyle.Fill;

            tabStatus.TabPages[0].PageVisible = true;
            tabStatus.TabPages[0].Controls.Add(ShelfStatus);

            ShelfStatus.Start(ModuleID, ref aConfig, ref SystemData);

            edModuleID.Enabled = false;
            chbPolling.Enabled = true;
        }

        private void TypeChangedUpdate(ref CommConfig aConfig)
        {
            // Display Screen Deletes
            if (ShelfStatus != null)
            {
                ShelfStatus.Dispose();
                ShelfStatus = null;
            }

            SetCellTempQty(aConfig, ref SystemData);
            try
            {
                ModuleID = Convert.ToInt16(edModuleID.Text);
            }
            catch (Exception)
            {
                ModuleID = 1;
            }

            switch (aConfig.CommType)
            {
                case csConstData.CommType.COMM_UART:
                    TypeChangeUpdateUart(ref aConfig);
                    historyToolStripMenuItem.Visible = true;
                    inventoryViewToolStripMenuItem.Visible = true;
                    updateToolStripMenuItem.Visible = false;
                    break;
                case csConstData.CommType.COMM_RS485:
                    TypeChangeUpdateRS485(ref aConfig);
                    historyToolStripMenuItem.Visible = true;
                    inventoryViewToolStripMenuItem.Visible = false;
                    updateToolStripMenuItem.Visible = true;
                    break;
                case csConstData.CommType.COMM_SNMP:
                    TypeChangeUpdateSnmp(ref aConfig);
                    historyToolStripMenuItem.Visible = true;
                    inventoryViewToolStripMenuItem.Visible = false;
                    updateToolStripMenuItem.Visible = false;
                    break;
                default:
                    break;
            }
            //DisplayCommStatus();
        }

        private void SetCellTempQty(CommConfig aConfig, ref DeviceSystemData[] SystemData)
        {
            switch (aConfig.CommType)
            {
                case csConstData.CommType.COMM_UART:
                case csConstData.CommType.COMM_RS485:
                    switch (aConfig.UartModelIndex)
                    {
                        case csConstData.MODEL_INDEX.LFPM_48100D:
                        case csConstData.MODEL_INDEX.LFPM_48150D:
                        case csConstData.MODEL_INDEX.LFPM_48200D:
                        case csConstData.MODEL_INDEX.LFPM_48250D:
                        case csConstData.MODEL_INDEX.LFPM_48300D:
                            for (int i = 0; i < SystemData.Length; i++)
                            {
                                SystemData[i].cellQty = 15;
                                SystemData[i].tempQty = 4;
                            }
                            break;
                        case csConstData.MODEL_INDEX.LFPM_124050D:
                            for (int i = 0; i < SystemData.Length; i++)
                            {
                                SystemData[i].cellQty = csConstData.SystemInfo.MAX_MODULE_CELL_SIZE;
                                SystemData[i].tempQty = csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE;
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case csConstData.CommType.COMM_SNMP:
                    switch (aConfig.SnmpModelIndex)
                    {
                        case csConstData.MODEL_INDEX.LFPM_48100D:
                        case csConstData.MODEL_INDEX.LFPM_48150D:
                        case csConstData.MODEL_INDEX.LFPM_48200D:
                        case csConstData.MODEL_INDEX.LFPM_48250D:
                        case csConstData.MODEL_INDEX.LFPM_48300D:
                            for (int i = 0; i < SystemData.Length; i++)
                            {
                                SystemData[i].cellQty = 15;
                                SystemData[i].tempQty = 4;
                            }
                            break;
                        case csConstData.MODEL_INDEX.LFPM_124050D:
                            for (int i = 0; i < SystemData.Length; i++)
                            {
                                SystemData[i].cellQty = csConstData.SystemInfo.MAX_MODULE_CELL_SIZE;
                                SystemData[i].tempQty = csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE;
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    for (int i = 0; i < SystemData.Length; i++)
                    {
                        SystemData[i].cellQty = 15;
                        SystemData[i].tempQty = 4;
                    }
                    break;
            }
        }

        private void UpdateDataUart(object sender, ref DeviceSystemData rData)
        {
            ShelfStatus?.UpdateData(ref SystemData);
            dbThread?.UpdateData(ModuleID, SystemData);
            uDataLog.UpdateData(SystemData);
        }
        private void UpdateDataRS485(object sender, ref DeviceSystemData[] rData)
        {
            ShelfStatus?.UpdateData(ref SystemData);
            dbThread?.UpdateData(ModuleID, SystemData);
            uDataLog.UpdateData(SystemData);
        }

        private void DisplaySystemFwVerModule()
        {
            switch (Config.ControlLevel)
            {
                case 0:         // User Level
                    inventoryViewToolStripMenuItem.Visible = false;
                    break;
                case 1:         // Technician Level
                    inventoryViewToolStripMenuItem.Visible = false;
                    break;
                case 2:         // Engineer Level
                    inventoryViewToolStripMenuItem.Visible = false;
                    break;
                case 3:         // Master Level
                    inventoryViewToolStripMenuItem.Visible = true;
                    break;
                default:        // User Level
                    inventoryViewToolStripMenuItem.Visible = false;
                    break;
            }

            switch (Config.ControlLevel)
            {
                case 0:             // User Level
                    this.Text = String.Format("LFP SYSTEM [{0}] -- DELTA - User Level", Application.ProductVersion);
                    break;
                case 1:             // Technician Level
                    this.Text = String.Format("LFP SYSTEM [{0}] -- DELTA - Technician Level", Application.ProductVersion);
                    break;
                case 2:             // Engineer Level
                    this.Text = String.Format("LFP SYSTEM [{0}] -- DELTA - Engineer Level", Application.ProductVersion);
                    break;
                case 3:             // Master Level
                    this.Text = String.Format("LFP SYSTEM [{0}] -- DELTA - Master Level", Application.ProductVersion);
                    break;
                default:
                    this.Text = String.Format("LFP SYSTEM [{0}] -- DELTA - User Level", Application.ProductVersion);
                    break;
            }

            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate ()
                {
                    if (SystemData[0].ValueData.fw_ver[0] != 0x00)
                    {
                        byte[] sn = new byte[33];
                        for (int i = 0; i < 32; i++)
                            sn[i] = SystemData[0].Information.BMS_SN[i];
                        sn[32] = 0;

                        tabStatus.TabPages[0].Text = String.Format("{0} [{1}] - {2}", "LFP MODULE"
                            , Encoding.UTF8.GetString(SystemData[0].ValueData.fw_ver)
                            , Encoding.Default.GetString(sn).Trim('\0')
                            );
                    }
                    else
                    {
                        tabStatus.TabPages[0].Text = String.Format("LFP MODULE");
                    }
                }));
            }
            else
            {
                if (SystemData[0].ValueData.fw_ver[0] != 0x00)
                {
                    byte[] sn = new byte[17];
                    for (int i = 0; i < 16; i++)
                        sn[i] = SystemData[0].Information.BMS_SN[i];         //22.06.30 Byul 32->16
                    sn[16] = 0;

                    tabStatus.TabPages[0].Text = String.Format("{0} [{1}] - {2}", "LFP MODULE"
                        , Encoding.UTF8.GetString(SystemData[0].ValueData.fw_ver).Trim('\0')
                        , Encoding.Default.GetString(sn).Trim('\0')
                        );
                }
                else
                {
                    tabStatus.TabPages[0].Text = String.Format("LFP MODULE");
                }
            }
        }

        private void UpdateSnmpData(object sender, ref DeviceSystemData rData)
        {
            uDataLog.UpdateData(SystemData);
        }

        private void UpdateConfig(object aConfig)
        {
            Config = (CommConfig)aConfig;

            IniLoad(ref Config);
        }

        #endregion

        #region MENU EVENT

        private void commConfigToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConfigButtonClick(sender, e);
        }

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

        private void testSendToolStripMenuItem_Click(object sender, EventArgs e)
        {
            csHistoryFunction.DbCreate(System.IO.Path.GetDirectoryName(Application.ExecutablePath));
        }

        private void firmwareUpdateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if ((rs485Thread == null) && (rs485Thread124050 == null))
            {
                return;
            }

            if (rs485Thread124050 != null)
            {
                FwUpdateForm = new fmxFwUpdate(rs485Thread124050.ModuleID);
            }
            else
            {
                FwUpdateForm = new fmxFwUpdate(rs485Thread.ModuleID);
            }

            FwUpdateForm.OnAutoTxSet += SetAutoTx;
            FwUpdateForm.OnSendUartData += SetWriteData;
            FwUpdateForm.ShowDialog();
        }

        private void historyViewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxHistory")
                {
                    frm.Activate();
                    return;
                }
            }
            HistoryForm = new fmxHistory(Config, ModuleID);

            HistoryForm.OnSendUartData += SetWriteData;
            HistoryForm.ShowDialog();
        }

        private void inventoryViewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxInventoryConfig")
                {
                    frm.Activate();
                    return;
                }
            }
            InventoryConfig = new fmxInventoryConfig(ModuleID, ref Config, ref SystemData[ModuleID - 1]);

            InventoryConfig.OnSendUartData += SetWriteData;
            InventoryConfig.Show();
        }

        #endregion

        #region FORM EVENT

        private void fmxMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (uartThread != null)
            {
                uartThread.disposeThread();
                uartThread = null;
            }
            if (rs232Thread124050 != null)
            {
                rs232Thread124050.disposeThread();
                rs232Thread124050 = null;
            }
            if (rs485Thread != null)
            {
                rs485Thread.disposeThread();
                rs485Thread = null;
            }
            if (rs485Thread124050 != null)
            {
                rs485Thread124050.disposeThread();
                rs485Thread124050 = null;
            }
            if (dbThread != null)
            {
                dbThread.disposeThread();
                dbThread = null;
            }
        }

        #endregion

        #region STATUS BAR EVENT

        void DisplayCommStatus()
        {
            if (Active == true)
                CommStatusBar.Text = "Comm: On";
            else
                CommStatusBar.Text = "Comm: Off";
        }

        void DisplayCommStatus(string msg)
        {
            if (msg != "")
                CommStatusBar.Text = String.Format("Comm: {0}", msg);
        }

        void LogStatusUpdate(object sender, string msg, bool active, int aLogTime)
        {
            LogStatusBar.Text = msg;

        }

        #endregion

        #region COMMAND AND SET

        private void CommDataPrint(object sender, string msg)
        {
            if (msg != "")
            {
                uEventLog.EventUpdate(msg + "\r\n");
            }
        }

        private void SetWriteData(ushort WriteAddr, byte[] WriteData, bool RelyFlag, int type)
        {
            uartThread?.SetWriteReg(WriteAddr, WriteData, RelyFlag, type);
            rs232Thread124050?.SetWriteReg(WriteAddr, WriteData, RelyFlag, type);
            rs485Thread?.SetWriteReg(WriteAddr, WriteData, RelyFlag, type);
            rs485Thread124050?.SetWriteReg(WriteAddr, WriteData, RelyFlag, type);
        }

        private void SetCmdEvent(int sId, int cmd, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib)
        {
            if (MainStatus != null)
            {
                switch (cmd)
                {
                    case 1:                 // Module quatity set
                        break;
                    case 2:
                        CreateModuleDetailForm(sId);
                        break;
                }
            }
            uartThread?.SendProcessFromApp(sId, cmd, index, flag, ref aParam, ref aCalib);
            rs232Thread124050?.SendProcessFromApp(sId, cmd, index, flag, ref aParam, ref aCalib);
        }

        private void CreateModuleDetailForm(int sID)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxModuleDetail")
                {
                    ((fmxModuleDetail)frm).SetModuleID(sID);
                    frm.Activate();
                    return;
                }
            }
            ModuleDetailForm = new fmxModuleDetail(sID, ref Config, ref SystemData);

            //ModuleDetailForm.OnAutoTxCanSet += SetAutoTxCan;
            //ModuleDetailForm.OnSendDataCan += SendDataToCan;
            ModuleDetailForm.Show();
        }

        private void chbPolling_CheckedChanged(object sender, EventArgs e)
        {
            if (edModuleID.Text != "")
            {
                ModuleID = Convert.ToInt32(edModuleID.Text);

                if (uartThread != null)
                {
                    uartThread.SetPolling(chbPolling.Checked, ModuleID, ref SystemData[ModuleID - 1]);
                    ShelfStatus?.UpdateSystemId(ModuleID);
                }
                if (rs232Thread124050 != null)
                {
                    rs232Thread124050.SetPolling(chbPolling.Checked, ModuleID, ref SystemData[ModuleID - 1]);
                    ShelfStatus?.UpdateSystemId(ModuleID);
                }
                if (rs485Thread != null)
                {
                    rs485Thread.SetPolling(chbPolling.Checked, ModuleID, ref SystemData);
                    ShelfStatus?.UpdateSystemId(ModuleID);
                }
                if (rs485Thread124050 != null)
                {
                    rs485Thread124050.SetPolling(chbPolling.Checked, ModuleID, ref SystemData);
                    ShelfStatus?.UpdateSystemId(ModuleID);
                }
                snmpThread?.SetAutoTx(chbPolling.Checked);
                snmpThread124050?.SetAutoTx(chbPolling.Checked);

                uDataLog.UpdateActiveStatus(Active, ModuleID, Config, SystemData);
                dbThread?.UpdateData(ModuleID, SystemData);

                edModuleID.Enabled = !chbPolling.Checked;
            }
        }

        private void SnmpRecvData(string result, bool error)
        {
            if (result != "")
            {
                uEventLog.EventUpdate(result + "\r\n");
            }
        }

        private void SetAutoTx(bool autoTx)
        {
            uartThread?.SetAutoTx(autoTx);
            rs232Thread124050?.SetAutoTx(autoTx);
        }
        #endregion

        #region KEYBOARD HOOK
        private void edSystemId_KeyPress(object sender, KeyPressEventArgs e)
        {
            csUtils.TypingOnlyNumber(sender, e, false, false);
        }
        #endregion

        #region MENU COMMAND
        private void inventoryControlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxInventoryConfig")
                {
                    frm.Activate();
                    return;
                }
            }
            InventoryConfig = new fmxInventoryConfig(0, ref Config, ref SystemData[0]);

            InventoryConfig.OnUpdate += UpdateInformation;
            InventoryConfig.OnCommand += InvDataSetCmd;
            //InventoryConfig.OnCommandBySnmp += SetInvEventBySnmp;
            InventoryConfig.Show();
        }

        private void InvDataSetCmd(int sId, int mode, int index, int flag, ref DeviceInforation aInvData)
        {
            SystemData[0].CalibrationData.InvData = aInvData;
            //OnCommand?.Invoke(sId, mode, index, flag, ref SystemData[0].ParamData, ref SystemData[0].CalibrationData);
            //SetCmdToCan(sId, mode, index, flag, ref SystemData[0].ParamData, ref SystemData[0].CalibrationData);
        }

        private void UpdateInformation(object sendor)
        {
            ((fmxInventoryConfig)sendor).UpdateData(ref SystemData[0]);
        }

        private void checkDBToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxExcelFile")
                {
                    frm.Activate();
                    return;
                }
            }
            fmxExcelFile DbControl = new fmxExcelFile(Config);

            DbControl.Show();
        }

        private void levelConfigToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void changeLeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "FmxLevelConfig")
                {
                    frm.Activate();
                    return;
                }
            }
            FmxLevelConfig LevelControl = new FmxLevelConfig(Config);

            LevelControl.ShowDialog();
        }

        private void changePasswordToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "FmxPasswordChange")
                {
                    frm.Activate();
                    return;
                }
            }
            FmxPasswordChange ChangePassword = new FmxPasswordChange(Config);

            ChangePassword.ShowDialog();
        }
        #endregion

        #region TIMER EVENT
        private void tmrDisplay_Tick(object sender, EventArgs e)
        {
            uTarget.UpdateStatus(Active);
            DisplaySystemFwVerModule();
        }
        #endregion
    }
}