using DevExpress.XtraCharts;
using LFP_Manager.DataStructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Threading;

namespace LFP_Manager.Controls
{
    public partial class ucMainStatus : DevExpress.XtraEditors.XtraUserControl
    {
        private delegate void CanIJust();

        private List<int> _valueList;
        private Thread _thread;
        private CanIJust _doIt;
        private Random _ran;
        private int _interval;

        private CommConfig Config;
        private DeviceSystemData SystemData;

        private DataTable dtVI;
        private DateTime OldTime;

        Series seriesVolt;
        Series seriesCurr;
        Series seriesTemp;
        Series seriesSoc;
        LineSeriesView currLineView;
        LineSeriesView tempLineView;
        LineSeriesView socLineView;
        SecondaryAxisY currAxisY;
        SecondaryAxisY tempAxisY;
        SecondaryAxisY socAxisY;

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

        private bool active = false;
        private bool ThreadEnd = false;

        private int logTimeSec = 5;

        public ucMainStatus()
        {
            InitializeComponent();

            InitDataTableVolt();
            InitChart();
        }

        public void SimStart()
        {
            _valueList = new List<int>();
            _ran = new Random();
            _interval = 500;
            GoBoy();
        }

        private void GoBoy()
        {
            _doIt += new CanIJust(AddData);

            _thread = new Thread(new ThreadStart(ComeOnYouThread));
            _thread.Start();
        }

        public void Start(CommConfig aConfig, ref DeviceSystemData aSystemData)
        {
            Config = aConfig;
            SystemData = aSystemData;

            reloadChart();

            _interval = 200;
            _doIt += new CanIJust(AddData);
            ThreadEnd = false;
            _thread = new Thread(new ThreadStart(ComeOnYouThread));
            _thread.Start();

            active = true;
            tmrDisplay.Start();
        }

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

            ThreadEnd = true;

            if (_thread != null)
            {
                if (_thread.IsAlive)
                    _thread.Abort();
            }
        }

        public void UpdateData(ref DeviceSystemData aSystemData)
        {
            if (active)
            {
                SystemData = aSystemData;

                TotalVoltage = (double)SystemData.ValueData.voltageOfPack / 10;
                TotalCurrent = (double)SystemData.ValueData.current / 10;
                TotalSoc = (double)SystemData.ValueData.rSOC / 10;
                TotalTemperature = (double)SystemData.AvgData.maxTemp / 10;
            }
        }

        private void InitDataTableVolt()
        {
            dtVI = new DataTable();

            dtVI.Columns.Add("DateTime", typeof(DateTime));

            dtVI.Columns.Add(String.Format("Volt"), typeof(double));
            dtVI.Columns.Add(String.Format("Curr"), typeof(double));
            dtVI.Columns.Add(String.Format("Temp"), typeof(double));
            dtVI.Columns.Add(String.Format("SOC"), typeof(double));

            // Add data rows to the table.
            DataRow row = null;

            row = dtVI.NewRow();
            row["DateTime"] = DateTime.Now;

            row[String.Format("Volt")] = 0;
            row[String.Format("Curr")] = 0;
            row[String.Format("Temp")] = 0;
            row[String.Format("SOC")] = 0;

            dtVI.Rows.Add(row);
        }

        private void InitChart()
        {
            chartVI.Series.Clear();
            chartVI.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False;
            chartVI.Titles[0].Visibility = DevExpress.Utils.DefaultBoolean.False;

            //-------------------- Series VOLT -----------------------//
            seriesVolt = new Series(String.Format("Volt"), ViewType.Line)
            {
                DataSource = dtVI,
                //seriesVolt.Label.PointOptions.PointView = PointView.Values;
                //seriesVolt.Label.PointOptions.ValueNumericOptions.Format = NumericFormat.Number;
                //seriesVolt.Label.PointOptions.ValueNumericOptions.Precision = 1;
                CrosshairLabelVisibility = DevExpress.Utils.DefaultBoolean.True,
                CrosshairLabelPattern = "{S} : {V:F1}V",
                //seriesVolt.CrosshairLabelPattern = "{S} {A:hh:mm:ss} : {V:F1}V";

                // Specify data members to bind the series.
                ArgumentScaleType = ScaleType.DateTime,
                ArgumentDataMember = "DateTime",
                ValueScaleType = ScaleType.Numerical
            };
            seriesVolt.ValueDataMembers.AddRange(new string[] { String.Format("Volt") });

            chartVI.Series.Add(seriesVolt);

            //-------------------- Series CURR -----------------------//
            seriesCurr = new Series(String.Format("Curr"), ViewType.Line)
            {
                DataSource = dtVI,

                //seriesCurr.Label.PointOptions.PointView = PointView.Values;
                //seriesCurr.Label.PointOptions.ValueNumericOptions.Format = NumericFormat.Number;
                //seriesCurr.Label.PointOptions.ValueNumericOptions.Precision = 1;
                CrosshairLabelVisibility = DevExpress.Utils.DefaultBoolean.True,
                CrosshairLabelPattern = "{S} : {V:F1}A",
                //seriesCurr.CrosshairLabelPattern = "{S} {A:hh:mm:ss} : {V:F1}A";

                // Specify data members to bind the series.
                ArgumentScaleType = ScaleType.DateTime,
                ArgumentDataMember = "DateTime",

                ValueScaleType = ScaleType.Numerical
            };
            seriesCurr.ValueDataMembers.AddRange(new string[] { String.Format("Curr") });

            chartVI.Series.Add(seriesCurr);

            //-------------------- Series TEMP -----------------------//
            seriesTemp = new Series(String.Format("Temp"), ViewType.Line)
            {
                DataSource = dtVI,

                //seriesTemp.Label.PointOptions.PointView = PointView.Values;
                //seriesTemp.Label.PointOptions.ValueNumericOptions.Format = NumericFormat.Number;
                //seriesTemp.Label.PointOptions.ValueNumericOptions.Precision = 1;
                CrosshairLabelVisibility = DevExpress.Utils.DefaultBoolean.True,
                CrosshairLabelPattern = "{S} : {V:F1}C",
                //seriesTemp.CrosshairLabelPattern = "{S} {A:hh:mm:ss} : {V:F1}A";

                // Specify data members to bind the series.
                ArgumentScaleType = ScaleType.DateTime,
                ArgumentDataMember = "DateTime",

                ValueScaleType = ScaleType.Numerical
            };
            seriesTemp.ValueDataMembers.AddRange(new string[] { String.Format("Temp") });

            chartVI.Series.Add(seriesTemp);

            //-------------------- Series SOC -----------------------//
            seriesSoc = new Series(String.Format("SOC"), ViewType.Line)
            {
                DataSource = dtVI,
                //seriesSoc.Label.PointOptions.PointView = PointView.Values;
                //seriesSoc.Label.PointOptions.ValueNumericOptions.Format = NumericFormat.Number;
                //seriesSoc.Label.PointOptions.ValueNumericOptions.Precision = 1;
                CrosshairLabelVisibility = DevExpress.Utils.DefaultBoolean.True,
                CrosshairLabelPattern = "{S} : {V:F1}%",
                //seriesTemp.CrosshairLabelPattern = "{S} {A:hh:mm:ss} : {V:F1}A";

                // Specify data members to bind the series.
                ArgumentScaleType = ScaleType.DateTime,
                ArgumentDataMember = "DateTime",

                ValueScaleType = ScaleType.Numerical
            };
            seriesSoc.ValueDataMembers.AddRange(new string[] { String.Format("SOC") });

            chartVI.Series.Add(seriesSoc);

            XYDiagram diagram = (XYDiagram)chartVI.Diagram;

            //diagram.AxisX.DateTimeScaleOptions.AggregateFunction = AggregateFunction.Sum;
            //diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Minute;
            //diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Second;

            diagram.AxisX.Title.Text = "Date Time (hh:mm:ss)";
            diagram.AxisX.Title.Visibility = DevExpress.Utils.DefaultBoolean.False;
            diagram.AxisX.Title.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular);
            //diagram.AxisX.Label.DateTimeOptions.Format = DevExpress.XtraCharts.DateTimeFormat.Custom;
            //diagram.AxisX.Label.DateTimeOptions.FormatString = "HH:mm:ss";

            diagram.AxisY.WholeRange.MaxValue = 60.0;
            diagram.AxisY.WholeRange.MinValue = 40.0;
            diagram.AxisY.WholeRange.Auto = false;
            diagram.AxisY.WholeRange.AlwaysShowZeroLevel = true;
            diagram.AxisY.VisualRange.MaxValue = 60.0;
            diagram.AxisY.VisualRange.MinValue = 40.0;
            diagram.AxisY.VisualRange.Auto = false;

            //diagram.AxisY.GridSpacing = 1;
            diagram.AxisY.Title.Text = "Voltage (V)";
            diagram.AxisY.Title.Visibility = DevExpress.Utils.DefaultBoolean.False;
            diagram.AxisY.Title.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Regular);

            chartVI.Diagram.Assign(diagram);

            currAxisY = new SecondaryAxisY("Current Y-Axis");
            ((XYDiagram)chartVI.Diagram).SecondaryAxesY.Add(currAxisY);

            //currAxisY.GridSpacing = 10D;
            //currAxisY.GridSpacingAuto = false;
            currAxisY.WholeRange.MinValue = "-300";
            currAxisY.WholeRange.MaxValue = "300";
            currAxisY.WholeRange.Auto = false;
            currAxisY.WholeRange.AlwaysShowZeroLevel = true;
            currAxisY.Visibility = DevExpress.Utils.DefaultBoolean.False;

            currAxisY.Title.Text = "Current (A)";
            currAxisY.Title.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Regular);
            currAxisY.Title.Visibility = DevExpress.Utils.DefaultBoolean.False;

            currLineView = new LineSeriesView();
            currLineView = (LineSeriesView)seriesCurr.View;
            currLineView.AxisY = currAxisY;
            currLineView.LineMarkerOptions.BorderVisible = false;
            currLineView.LineMarkerOptions.Color = Color.Red;
            currLineView.LineStyle.Thickness = 2;
            currLineView.MarkerVisibility = DevExpress.Utils.DefaultBoolean.False;
            currLineView.Shadow.Visible = false;

            tempAxisY = new SecondaryAxisY("Temperature Y-Axis");
            ((XYDiagram)chartVI.Diagram).SecondaryAxesY.Add(tempAxisY);

            //tempAxisY.GridSpacing = 5D;
            //tempAxisY.GridSpacingAuto = false;
            tempAxisY.WholeRange.MinValue = "-25.0";
            tempAxisY.WholeRange.MaxValue = "80.0";
            tempAxisY.WholeRange.Auto = false;
            tempAxisY.WholeRange.AlwaysShowZeroLevel = true;
            tempAxisY.Visibility = DevExpress.Utils.DefaultBoolean.False;

            tempAxisY.Title.Text = "Temperature (C)";
            tempAxisY.Title.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Regular);
            tempAxisY.Title.Visibility = DevExpress.Utils.DefaultBoolean.False;

            tempLineView = new LineSeriesView();
            tempLineView = (LineSeriesView)seriesTemp.View;
            tempLineView.AxisY = tempAxisY;
            tempLineView.LineMarkerOptions.BorderVisible = false;
            tempLineView.LineMarkerOptions.Color = Color.Red;
            tempLineView.LineStyle.Thickness = 2;
            tempLineView.MarkerVisibility = DevExpress.Utils.DefaultBoolean.False;
            tempLineView.Shadow.Visible = false;

            // SOC AxisY
            socAxisY = new SecondaryAxisY("SOC Y-Axis");
            ((XYDiagram)chartVI.Diagram).SecondaryAxesY.Add(socAxisY);

            //socAxisY.GridSpacing = 10D;
            //socAxisY.GridSpacingAuto = false;
            socAxisY.WholeRange.MinValue = "-2.0";
            socAxisY.WholeRange.MaxValue = "102.0";
            socAxisY.WholeRange.Auto = false;
            socAxisY.WholeRange.AlwaysShowZeroLevel = true;
            socAxisY.Visibility = DevExpress.Utils.DefaultBoolean.False;

            socAxisY.Title.Text = "SOC (%)";
            socAxisY.Title.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Regular);
            socAxisY.Title.Visibility = DevExpress.Utils.DefaultBoolean.False;

            socLineView = new LineSeriesView();
            socLineView = (LineSeriesView)seriesSoc.View;
            socLineView.AxisY = socAxisY;
            socLineView.LineMarkerOptions.BorderVisible = false;
            socLineView.LineMarkerOptions.Color = Color.Red;
            socLineView.LineStyle.Thickness = 2;
            socLineView.MarkerVisibility = DevExpress.Utils.DefaultBoolean.False;
            socLineView.Shadow.Visible = false;
        }

        private void reloadChart()
        {
            chartVI.Series.Clear();

            //for (int i = 0; i < mQty; i++)
            //{
                chartVI.Series.Add(seriesVolt);
            //}

            //for (int i = 0; i < mQty; i++)
            //{
                chartVI.Series.Add(seriesCurr);
            //}

            //for (int i = 0; i < mQty; i++)
            //{
                chartVI.Series.Add(seriesTemp);
            //}

            //for (int i = 0; i < mQty; i++)
                //{
                chartVI.Series.Add(seriesSoc);
            //}
        }

        private void ComeOnYouThread()
        {
            while (ThreadEnd == false)
            {
                try
                {
                    chartVI.Invoke(_doIt);

                    Thread.Sleep(_interval);
                }
                catch (Exception)
                {
                }
            }
        }

        public void SetLogTime(int aSec)
        {
            logTimeSec = aSec;
        }

        private void AddData()
        {
            DateTime now = DateTime.Now;
            TimeSpan dTime = now - OldTime;

            //if (OldTime.Second != now.Second)
            if ((dTime.Seconds >= logTimeSec) && ((now.Second % logTimeSec) == 0))
            {
                if (dtVI.Rows.Count > 1000)
                {
                    dtVI.Rows.RemoveAt(0);
                }

                // Add data rows to the table.
                DataRow row = null;

                row = dtVI.NewRow();
                row["DateTime"] = DateTime.Now;

                row[String.Format("Volt")] = TotalVoltage;
                row[String.Format("Curr")] = TotalCurrent;
                row[String.Format("Temp")] = TotalTemperature;
                row[String.Format("SOC")] = TotalSoc;

                dtVI.Rows.Add(row);

                OldTime = now;
            }
        }

        private void tmrDisplay_Tick(object sender, EventArgs e)
        {
            DisplayTotalValue();
            DisplayStatusAndAlarm();
        }

        private void DisplayTotalValue()
        {
            if (active)
            {
                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);

                chartVI.Invalidate();
            }
        }

        private void DisplayStatusAndAlarm()
        {
            if (SystemData.CommFail == false)
            {
                // Operating Status
                if (SystemData.StatusData.status == 0)
                {
                    lbStatus.Text = "STANDBY";
                    lbStatus.ForeColor = System.Drawing.Color.Black;
                }
                else if (SystemData.StatusData.status == 1)
                {
                    lbStatus.Text = "CHARGING";
                    lbStatus.ForeColor = System.Drawing.Color.Blue;
                }
                else if (SystemData.StatusData.status == 2)
                {
                    lbStatus.Text = "DISCHARGING";
                    lbStatus.ForeColor = System.Drawing.Color.Magenta;
                }
                else if (SystemData.StatusData.status == 3)
                {
                    lbStatus.Text = "FLOATING";
                    lbStatus.ForeColor = System.Drawing.Color.Black;
                }
                else
                {
                    lbStatus.Text = "UNKNOWN";
                    lbStatus.ForeColor = System.Drawing.Color.Black;
                }
                // Alarm Display
                if (SystemData.StatusData.alarm == 0)
                {
                    lbAlarm.Text = "NORMAL";
                    lbAlarm.ForeColor = System.Drawing.Color.Green;
                }
                else if (SystemData.StatusData.alarm == 1)
                {
                    lbAlarm.Text = "WARNING";
                    lbAlarm.ForeColor = System.Drawing.Color.Orange;
                }
                else if (SystemData.StatusData.alarm == 2)
                {
                    lbAlarm.Text = "FAULT";
                    lbAlarm.ForeColor = System.Drawing.Color.Red;
                }
                else if (SystemData.StatusData.alarm == 3)
                {
                    lbAlarm.Text = "WARMING UP";
                    lbAlarm.ForeColor = System.Drawing.Color.Green;
                }
                else
                {
                    lbAlarm.Text = "UNKNOWN";
                    lbAlarm.ForeColor = System.Drawing.Color.Red;
                }
            }
            else
            {
                lbStatus.Text = "OFF LINE";
                lbStatus.ForeColor = System.Drawing.Color.Red;
                lbAlarm.Text = "OFF LINE";
                lbAlarm.ForeColor = System.Drawing.Color.Red;
            }
        }
    }
}
