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

using LFP_Manager.Forms;
using LFP_Manager.DataStructure;
using LFP_Manager.Utils;

namespace LFP_Manager.Controls
{
    public delegate void setCalibUpdate(object sender);
    public delegate void setCalibCommand(int mode, int flag, ref DeviceCalibration aCalib, ref DeviceSystemTotalData aTotal);
    public delegate Int32 getBattData(int item, int cno);

    public partial class ucCalibration : DevExpress.XtraEditors.XtraUserControl
    {
        #region DEFINE

        const string FORCED_BALANCING_OFF = "OFF";
        const string FORCED_BALANCING_ON = "ON";
        const string FORCED_BALANCING_TEST = "TEST";

        const string MANUAL_BAL_DISABLE = "DISABLE";
        const string MANUAL_BAL_ENABLE = "ENABLE";

        const string MANUAL_BAL_MODE_BUCK = "BUCK_MODE";
        const string MANUAL_BAL_MODE_BOOST = "BOOST_MODE";

        const string CURR_CALIB_CHARGE = "CHARGE";
        const string CURR_CALIB_DISCHAGE = "DISCHARGE";

        #endregion

        #region VARIABLES

        DeviceCalibration rCalib;
        DeviceCalibration wCalib;
        DeviceSystemTotalData wTotal;

        //UInt32 cValue = 0;

        //bool wFlag = false;

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

        #endregion

        #region CONSTRUCTORS

        // Battery No:
        //     0: No 1,3,5,7,9,11,13,15 ODD
        //     1: No 2,4,6,8,10,12,14 Even
        public ucCalibration()
        {
            InitializeComponent();

            ComponentInit();

            wTotal = new DeviceSystemTotalData();
        }

        private void ComponentInit()
        {
            cbFcControl.Properties.Items.Clear();
            cbFcControl.Properties.Items.Add(FORCED_BALANCING_OFF);
            cbFcControl.Properties.Items.Add(FORCED_BALANCING_ON);
            cbFcControl.Properties.Items.Add(FORCED_BALANCING_TEST);
            cbFcControl.SelectedIndex = 1;

            cbFcCellNo.Properties.Items.Clear();
            for (int i = 0; i < csConstData.SystemInfo.MAX_MODULE_CELL_SIZE; i++)
            {
                cbFcCellNo.Properties.Items.Add(String.Format("{0}", i + 1));
            }
            cbFcCellNo.SelectedIndex = 0;

            CbBalEnable.Properties.Items.Clear();
            CbBalEnable.Properties.Items.Add(MANUAL_BAL_DISABLE);
            CbBalEnable.Properties.Items.Add(MANUAL_BAL_ENABLE);
            CbBalEnable.SelectedIndex = 0;

            CbBalMode.Properties.Items.Clear();
            CbBalMode.Properties.Items.Add(MANUAL_BAL_MODE_BOOST);
            CbBalMode.Properties.Items.Add(MANUAL_BAL_MODE_BUCK);
            CbBalMode.SelectedIndex = 0;
        }

        #endregion

        #region EXT EVENT FUNCTION

        private void OnCommnadEvent(int mode, int flag, ref DeviceCalibration aCalib, ref DeviceSystemTotalData aTotal)
        {
            OnCommand?.Invoke(mode, flag, ref aCalib, ref aTotal);
        }

        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(DeviceCalibration aCalib)
        {
            rCalib = aCalib;
            DisplayCalib();
        }

        #endregion

        #region DISPLAY DATA

        private void DisplayCalib()
        {
            // Cell Voltage Offset
            edCvOffset1.Text = String.Format("{0}", rCalib.CellVoltge.CvOffsetLow);
            edCvOffset2.Text = String.Format("{0}", rCalib.CellVoltge.CvOffsetHigh);

            // Device Address
            edSystemAddr.Text = String.Format("{0:0}", rCalib.SystemInfo.devAddr);

            // Cell Balancing Parameter
            TeCbThresholdCurr.Text = string.Format("{0}", rCalib.CbParam.Threadhold);
            TeCbWindowCurr.Text = string.Format("{0}", rCalib.CbParam.Window);
            TeCbMinCurr.Text = string.Format("{0}", rCalib.CbParam.Min);
            TeCbIntervalCurr.Text = string.Format("{0}", rCalib.CbParam.Interval);
        }

        #endregion

        #region BUTTON EVENT

        private void btnFcSet_Click(object sender, EventArgs e)
        {
            try
            {
                if (CbBalEnable.Text != null)
                {
                    wCalib = rCalib;
                    int cControl = cbFcControl.SelectedIndex;
                    int cNo = cbFcCellNo.SelectedIndex + 1;
                    int bMode = CbBalMode.SelectedIndex;
                    int bEnable = CbBalEnable.SelectedIndex;

                    wCalib.ForcedBalancing2.Control = cControl;
                    wCalib.ForcedBalancing2.CellNo = cNo;
                    wCalib.ForcedBalancing2.Mode = bMode;
                    wCalib.ForcedBalancing2.Enable = bEnable;

                    OnCommnadEvent(12, 1, ref wCalib, ref wTotal);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnBpGet_Click(object sender, EventArgs e)
        {
            OnCommnadEvent(15, 0, ref wCalib, ref wTotal);
        }

        private void btnBpSet_Click(object sender, EventArgs e)
        {
            if (edCvOffsetNew1.Text == "") return;
            if (edCvOffsetNew2.Text == "") return;

            wCalib = rCalib;
            wCalib.CellVoltge.CvOffsetLow = (short)(Convert.ToInt32(edCvOffsetNew1.Text));
            wCalib.CellVoltge.CvOffsetHigh = (short)(Convert.ToInt32(edCvOffsetNew2.Text));
            OnCommnadEvent(15, 1, ref wCalib, ref wTotal);
        }

        private void btnBmsAddrGet_Click(object sender, EventArgs e)
        {
            OnCommnadEvent(9, 0, ref wCalib, ref wTotal);
        }

        private void btnBmsAddrSet_Click(object sender, EventArgs e)
        {
            if (edSystemAddrNew.Text == string.Empty) return;
            wCalib = rCalib;
            wCalib.SystemInfo.devAddr = (UInt16)(Convert.ToInt32(edSystemAddrNew.Text));

            OnCommnadEvent(9, 1, ref wCalib, ref wTotal);
        }

        private void btnCanSpeedGet_Click(object sender, EventArgs e)
        {
            OnCommnadEvent(8, 0, ref wCalib, ref wTotal);
        }

        private void btnCanSpeedSet_Click(object sender, EventArgs e)
        {

        }

        private void TextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            csUtils.TypingOnlyNumber(sender, e, true, true);
        }
        private void BtnCbParamGet_Click(object sender, EventArgs e)
        {
            OnCommnadEvent(17, 0, ref wCalib, ref wTotal);
        }

        private void BtnCbParamSet_Click(object sender, EventArgs e)
        {
            if (TeCbThresholdNew.Text == "") return;
            if (TeCbWindowNew.Text == "") return;
            if (TeCbMinNew.Text == "") return;
            if (TeCbIntervalNew.Text == "") return;

            wCalib = rCalib.DeepCopy();
            wCalib.CbParam.Threadhold = (short)Convert.ToInt32(TeCbThresholdNew.Text);
            wCalib.CbParam.Window = (short)Convert.ToInt32(TeCbWindowNew.Text);
            wCalib.CbParam.Min = (short)Convert.ToInt32(TeCbMinNew.Text);
            wCalib.CbParam.Interval = (short)Convert.ToInt32(TeCbIntervalNew.Text);
            OnCommnadEvent(17, 1, ref wCalib, ref wTotal);
        }
        private void BtnCbDefault_Click(object sender, EventArgs e)
        {
            TeCbThresholdNew.Text = "3450";
            TeCbWindowNew.Text = "60";
            TeCbMinNew.Text = "10";
            TeCbIntervalNew.Text = "5";
        }
        #endregion

        #region COMPONENT EVENT
        private void edModuleNo_EditValueChanged(object sender, EventArgs e)
        {
            if (edModuleNo.Text != "")
            {
                int mdID;
                int mdNo;
                string strMdNo = edModuleNo.Text;

                try
                {
                    mdNo = Convert.ToInt32(strMdNo);

                    mdID = (mdNo - 1) % 14 + 1;

                    edSystemAddrNew.Text = mdID.ToString();
                }
                catch (Exception ex)
                {
                    edModuleNo.Text = "";
                    MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        #endregion
    }
}
