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;

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

        private fmxFwUpdate FwUpdateForm = null;
        private fmxExcelFile DbControlFrom = null;

        private CommConfig Config;
        private DeviceSystemData SystemData;

        private csCanThread canThread = null;
        private csValueCanThread ValueCanThread = null;

        private csDbThread dbThread = null;

        private ucShelfStatus SystemStatus;

        private bool Active = false;

        #endregion

        #region CONSTRUCTORS

        public fmxMain()
        {
            InitializeComponent();

            ComponentInit();

            StructDataInit();

            IniLoad();

            DataInit();

            ucCommConfig.OnStart += StartButtonClick;

            uDataLog.OnUpdate += LogStatusUpdate;

            edSystemId.Enabled = false;

            SystemStatus.OnCommand += SetCmdToCan;
            SystemStatus.OnMsgPrint += TestLogMessage;
            SystemStatus.Start(0, ref Config, ref SystemData);
            edSystemId.Enabled = true;

            ModuleIdSet.OnCommand += SetCmdToCan;

            //this.Text = String.Format("LFP SYSTEM [{0}] -- PR-LFP MODULE", Application.ProductVersion);
            this.Text = String.Format("LFP SYSTEM [{0}] -- PR-LFP MODULE - [{1}]"
                , Application.ProductVersion
                , csConstData.CommType.CAN_MODEL[Config.TargetModelIndex]
                );

            tmrCheckThreadMsg.Start();
        }

        private void ComponentInit()
        {
            SystemStatus = ucSystem;
        }

        private void IniLoad()
        {
            Config = csIniControlFunction.IniLoad(Application.ExecutablePath, Config);
            ucCommConfig.UpdateConfig(ref Config);
            TypeChangedUpdate(ref Config);
        }

        private void StructDataInit()
        {
            SystemData = new DeviceSystemData();
            Config = new CommConfig();
        }

        private void DataInit()
        {
            DataFunction.DataInit(ref SystemData, ref Config);
        }
        #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();
            CommConfigForm.Owner = this;

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

        private void StopProcess()
        {
            if (canThread != null)
            {
                canThread.disposeThread();
                canThread = null;
            }

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

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

            Active = false;

            edSystemId.Enabled = true;
            chbPolling.Enabled = true;

            DataInit();
            UpdateData(this, ref SystemData);
        }

        private void StartProcessCAN()
        {
            // CAN MODE
            int sId = 0;

            if (edSystemId.Text != null)
                sId = Convert.ToInt16(edSystemId.Text);

            ucSystem.SystemIdSet(sId);

            canThread = new csCanThread(sId, Config, ref SystemData);
            canThread.OnUpdate += UpdateData;
            canThread.OnDataRecv += CanRecvData;
            canThread.OnPrint += PrintLogMessage;

            if (canThread.Start(ref Config, sId, chbPolling.Checked))
            {
                Active = true;
                edSystemId.Enabled = false;
                chbPolling.Enabled = true;

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

                canThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));

                dbThread = new csDbThread(ref Config, ref SystemData);
                dbThread.Start(Config);
            }
            else
            {
                if (canThread != null)
                {
                    canThread.disposeThread();
                    canThread = null;
                }
            }
        }

        private void StartProcessValueCAN()
        {
            int sId = 0;

            if (edSystemId.Text != null)
                sId = Convert.ToInt16(edSystemId.Text);

            ucSystem.SystemIdSet(sId);

            ValueCanThread = new csValueCanThread(sId, Config, ref SystemData);
            ValueCanThread.OnUpdate += UpdateData;
            ValueCanThread.OnDataRecv += CanRecvData;
            ValueCanThread.OnPrint += PrintLogMessage;

            if (ValueCanThread.Start(Config, sId, chbPolling.Checked))
            {
                Active = true;
                edSystemId.Enabled = false;
                chbPolling.Enabled = true;

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

                ValueCanThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));

                dbThread = new csDbThread(ref Config, ref SystemData);
                dbThread.Start(Config);
            }
            else
            {
                if (ValueCanThread != null)
                {
                    ValueCanThread.disposeThread();
                    ValueCanThread = null;
                }
            }
        }

        private void StartButtonClick(object sender, EventArgs e)
        {
            if (Active)
            {
                StopProcess();
            }
            else
            {
                switch (Config.CommType)
                {
                    case csConstData.CommType.COMM_USBCAN:
                        switch (csCanConstData.CanDeviceInfo.DeviceIds[Config.CanDevice])
                        {
                            case csCanConstData.CanDeviceInfo.VCI_VALUE_CAN4_1:         // CAN MODE - ValueCAN
                                try
                                {
                                    StartProcessValueCAN();
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                    if (ValueCanThread != null)
                                    {
                                        ValueCanThread.disposeThread();
                                        ValueCanThread = null;
                                    }
                                }
                                break;
                            default:        // CAN MODE - USBCAN
                                try
                                {
                                    StartProcessCAN();
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                    if (canThread != null)
                                    {
                                        canThread.disposeThread();
                                        canThread = null;
                                    }
                                }
                                break;
                        }
                        break;
                }
            }

            if (canThread != null)
            {
                // USBCAN
                ucCommConfig.UpdateStatus(Active, canThread.GetCommSystemId());
            }
            else if (ValueCanThread != null)
            {
                // Value CAN
                ucCommConfig.UpdateStatus(Active, ValueCanThread.GetCommSystemId());
            }
            else
                { ucCommConfig.UpdateStatus(Active, 0); }

            uDataLog.UpdateActiveStatus(Active, Config, ref SystemData);
        }
        #endregion

        #region UPDATE FUNCTIONS

        private void UpdateCommConfigStatus()
        {
            if (canThread != null)
            {
                // USBCAN
                ucCommConfig.UpdateStatus(Active, canThread.GetCommSystemId());
            }
            else if (ValueCanThread != null)
            {
                // Value CAN
                ucCommConfig.UpdateStatus(Active, ValueCanThread.GetCommSystemId());
            }
            else
            {
                ucCommConfig.UpdateStatus(Active, 0);
            }
        }

        private void TypeChangedUpdate(ref CommConfig aConfig)
        {
            this.Text = String.Format("LFP SYSTEM [{0}] -- PR-LFP MODULE - [{1}]"
                , Application.ProductVersion
                , csConstData.CommType.CAN_MODEL[aConfig.TargetModelIndex]
                );

            switch (Config.TargetModelIndex)
            {
                case 0:             // PR-57150
                    edMaxModule.Text = "18";
                    break;
                case 1:             // PR-64150
                    edMaxModule.Text = "3";
                    break;
                case 2:             // LFPM-57080
                    edMaxModule.Text = "18";
                    break;
                case 3:             // PR-102150
                    edMaxModule.Text = "11";
                    break;
                case 4:             // PR-115300
                    edMaxModule.Text = "10";
                    break;
                case 5:             // PR-67150
                    edMaxModule.Text = "3";
                    break;
                default:
                    break;
            }

            DataInit();

            switch (aConfig.CommType)
            {
                case csConstData.CommType.COMM_USBCAN:
                    SystemStatus.Start(0, ref Config, ref SystemData);
                    edSystemId.Enabled = true;
                    break;
                case csConstData.CommType.COMM_UARTCAN:
                    SystemStatus.Start(0, ref Config, ref SystemData);
                    edSystemId.Enabled = true;
                    break;
            }
        }

        private void UpdateData(object sender, ref DeviceSystemData rData)
        {
            //SystemData = rData;

            //if (SystemStatus != null)
            //    SystemStatus.UpdateData(ref SystemData);
            //if (uDataLog != null)
            //    uDataLog.UpdateData(ref SystemData);
            //if (dbThread != null)
            //    dbThread.UpdateData(ref SystemData);

            if (edSystemId.Text != string.Empty)
                ModuleIdSet.UpdateData(Convert.ToInt32(edSystemId.Text), SystemData.CalibriationData);
        }

        private void CanRecvData(UInt32 hdr, byte[] data)
        {
            if (FwUpdateForm != null)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new MethodInvoker(delegate()
                    {
                        FwUpdateForm.RecvData(hdr, data);
                    }));
                }
                else
                {
                    FwUpdateForm.RecvData(hdr, data);
                }
            }
        }

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

            IniLoad();
        }

        #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 firmwareUpdateCANToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxFwUpdate")
                {
                    frm.Activate();
                    return;
                }
            }
            FwUpdateForm = new fmxFwUpdate(Convert.ToUInt32(edSystemId.Text), Config);

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

        private void firmwareImageConveterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form frm in Application.OpenForms)
            {
                if (frm.Name == "fmxFwImageConverter")
                {
                    frm.Activate();
                    return;
                }
            }
            fmxFwImageConverter FwImageConverter = new fmxFwImageConverter();

            FwImageConverter.Show();
        }

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

            HistoryForm.Show();
        }

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

            DbControlFrom.Show();
        }

        #endregion

        #region FORM EVENT

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

        private void fmxMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (canThread != null)
            {
                canThread.disposeThread();
                canThread = null;
            }

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

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

        #endregion

        #region TIMER EVENT

        private void tmrCheckThreadMsg_Tick(object sender, EventArgs e)
        {
            UpdateCommConfigStatus();

            //if (snmpThread != null)
            //{
            //    string data = snmpThread.GetResult();

            //    if (data != "")
            //    {
            //        uEventLog.EventUpdate(data + "\r\n");
            //    }
            //}

            //if (uartThread != null)
            //{
            //    string data = uartThread.GetMsg();

            //    if (data != "")
            //    {
            //        uEventLog.EventUpdate(data + "\r\n");
            //    }
            //}

            //if (canThread != null)
            //{
            //    string data = canThread.GetMsg();

            //    if (data != "")
            //    {
            //        uEventLog.EventUpdate(data + "\r\n");
            //    }
            //}

            //if (dbThread != null)
            //{
            //    string data = dbThread.GetMsg();

            //    if (data != "")
            //    {
            //        uEventLog.EventUpdate(data + "\r\n");
            //    }
            //}
            byte[] sn = new byte[17];

            switch (Config.CommType)
            {
                case csConstData.CommType.COMM_SNMP:
                    // SNMP MODE
                    break;
                case csConstData.CommType.COMM_UARTCAN:
                    // UARTCAN MODE
                    for (int i = 0; i < 16; i++)
                        sn[i] = SystemData.Information.pcb_sn[i];
                    sn[16] = 0;
                    if (sn[0] == 0xFF) sn[0] = 0;
                    pgSystem.Text = String.Format("{0} [{1}.{2}.{3}.{4}] - {5}", "LFP SYSTEM"
                        , SystemData.ValueData.fw_ver[0]
                        , SystemData.ValueData.fw_ver[1]
                        , SystemData.ValueData.fw_ver[2]
                        , SystemData.ValueData.fw_ver[3]
                        , Encoding.Default.GetString(sn)
                        );
                    break;
                case csConstData.CommType.COMM_USBCAN:
                    // USBCAN MODE
                    for (int i = 0; i < 16; i++)
                        sn[i] = SystemData.Information.pcb_sn[i];
                    sn[16] = 0;
                    if (sn[0] == 0xFF) sn[0] = 0;
                    pgSystem.Text = String.Format("{0} [{1}.{2}.{3}.{4}] - {5}", "LFP SYSTEM"
                        , SystemData.ValueData.fw_ver[0]
                        , SystemData.ValueData.fw_ver[1]
                        , SystemData.ValueData.fw_ver[2]
                        , SystemData.ValueData.fw_ver[3]
                        , Encoding.Default.GetString(sn)
                        );
                    break;
            }
            DisplayCommStaus();
        }

        #endregion

        #region STATUS BAR EVENT

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

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

        #endregion

        #region LOG PRINT FUCTION

        private void PrintLogMessage(object sender, string msg)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate ()
                {
                    uEventLog.EventUpdate(msg + "\r\n");
                }));
            }
            else
            {
                uEventLog.EventUpdate(msg + "\r\n");
            }
        }

        private void TestLogMessage(object sender, string msg)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate ()
                {
                    uEventLog.MsgUpdate(msg + "\r\n");
                }));
            }
            else
            {
                uEventLog.MsgUpdate(msg + "\r\n");
            }
        }

        #endregion

        #region CAN COMMAND AND SET

        private void SetCmdToCan(int sId, int mode, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib)
        {
            if (canThread != null)
            {
                canThread.SendProcessFromApp(sId, mode, flag, 0, ref aParam, ref aCalib);
            }
            else if (ValueCanThread != null)
            {
                ValueCanThread.SendProcessFromApp(sId, mode, flag, 0, ref aParam, ref aCalib);
            }
        }

        private void chbPolling_CheckedChanged(object sender, EventArgs e)
        {
            if (edSystemId.Text != string.Empty)
            {
                if (canThread != null)
                {
                    canThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
                }

                if (ValueCanThread != null)
                {
                    ValueCanThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
                }

                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));

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

        private void chkDcp_CheckedChanged(object sender, EventArgs e)
        {
            if (canThread != null)
            {
                if (chkDcp.Checked)
                    canThread.SetDcp(1);
                else
                    canThread.SetDcp(0);
            }

            if (ValueCanThread != null)
            {
                if (chkDcp.Checked)
                    ValueCanThread.SetDCP(1);
                else
                    ValueCanThread.SetDCP(0);
            }
        }

        private void edSystemId_KeyPress(object sender, KeyPressEventArgs e)
        {
            csUtils.TypingOnlyNumber(sender, e, false, false);
        }

        private void SendDataToCan(UInt32 header, byte[] data)
        {
            if (canThread != null)
            {
                canThread.SendDataFromApp(header, data, 0);
            }
            else if (ValueCanThread != null)
            {
                ValueCanThread.SendDataFromApp(header, data);
            }
        }

        private void SetAutoTxCan(bool autoTx)
        {
            if (canThread != null)
            {
                canThread.SetAutoTx(autoTx);
            }
            else if (ValueCanThread != null)
            {
                ValueCanThread.SetAutoTx(autoTx);
            }
        }

        private void tmrTest_Tick(object sender, EventArgs e)
        {
            //string data = "";

            //data += String.Format("S[{0}], ", SystemTotalData.AvgData.avgCellVoltage);
            //data += String.Format("S[{0}], ", SystemTotalData.AvgData.maxCellVoltage);
            //data += String.Format("S[{0}], ", SystemTotalData.AvgData.minCellVoltage);
            //data += String.Format("S[{0}], ", SystemTotalData.AvgData.diffCellVoltage);
            //data += String.Format("S[{0}], ", SystemTotalData.CellBalancingVoltage);
            //for (int i = 0; i < Config.CanModelIndex + 1; i++)
            //{
            //    data += String.Format("M-{0:00}[{1}], ", i + 1, SystemData.StatusData.cellBalanceValue);
            //}

            //if (data != "")
            //{
            //    uEventLog.EventUpdate(data + "\r\n");
            //}
        }

        private void btnNextID_Click(object sender, EventArgs e)
        {
            if (edSystemId.Text == "") return;
            if (edMaxModule.Text == "") return;

            int currID = Convert.ToInt32(edSystemId.Text);
            int maxModule = Convert.ToInt32(edMaxModule.Text);

            if (currID == maxModule)
                currID = 1;
            else
                currID++;

            edSystemId.Text = currID.ToString();
            SystemData.mNo = currID;

            if (canThread != null)
            {
                DataInit();
                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));
                canThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
            }
            else if (ValueCanThread != null)
            {
                DataInit();
                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));
                ValueCanThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
            }
        }

        private void btnPrevID_Click(object sender, EventArgs e)
        {
            if (edSystemId.Text == "") return;
            if (edMaxModule.Text == "") return;

            int currID = Convert.ToInt32(edSystemId.Text);
            int maxModule = Convert.ToInt32(edMaxModule.Text);

            if (currID == 1)
                currID = maxModule;
            else if (currID > 0)
                currID--;
            else
                currID = 1;

            edSystemId.Text = currID.ToString();
            SystemData.mNo = currID;

            if (canThread != null)
            {
                DataInit();
                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));
                canThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
            }
            else if (ValueCanThread != null)
            {
                DataInit();
                SystemStatus.UpdateSystemId(Convert.ToInt32(edSystemId.Text));
                ValueCanThread.SetPolling(chbPolling.Checked, Convert.ToInt32(edSystemId.Text), ref SystemData);
            }
        }

        private void edMaxModule_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                int id = Convert.ToInt32(edMaxModule.Text);
                ModuleIdSet.SetMaxModule(id);
            }
            catch (Exception ex)
            {
                MessageBox.Show("EditValue change error: " + ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion
    }
}