using Connection;
using Connection.Class;
using System;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WBP_Office_Vascular.Class;
using WBP_Office_Vascular.Enum;

namespace WBP_Office_Vascular_API_Demo_Customer {

    public partial class Form1 : Form {

        public Form1() {
            FormClosing += Form_Closing;
            InitializeComponent();
            System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
            var WBP_Office_VascularInfo = System.Reflection.Assembly.GetAssembly(typeof(WBP_Office_Vascular.WBP_Office_Vascular)).GetName();
            Text = $"{assembly.GetName().Name}  v{assembly.GetName().Version}           {WBP_Office_VascularInfo.Name}  v{WBP_Office_VascularInfo.Version}";
            comboBox_SW_AFib.SelectedIndex = 1;
            comboBox_SW_AMPM.SelectedIndex = 0;
            comboBox_SW_hide.SelectedIndex = 1;
            comboBox_SW_CBP.SelectedIndex = 1;
            comboBox_SW_Kpa.SelectedIndex = 0;
            comboBox_SW_SEL_silent.SelectedIndex = 1;
            comboBox_SW_SkipRest.SelectedIndex = 0;

            comboBox_Fun_SEL_AFIB.SelectedIndex = 1;
            comboBox_Fun_SEL_AMPM.SelectedIndex = 1;
            comboBox_AutoMeasureNumber.SelectedIndex = 2;
            comboBox_Fun_SEL_Bluetooth.SelectedIndex = 1;
            comboBox_Fun_SEL_CBP.SelectedIndex = 1;
            comboBox_Fun_SEL_RS232.SelectedIndex = 0;
            comboBox_Fun_SEL_UnitKpa.SelectedIndex = 1;
            comboBox_SW_AVG_no_include_first.SelectedIndex = 0;
            comboBox_ConnectType.SelectedIndex = 0;
            comboBox_HI_infPressure.SelectedIndex = 0;
            comboBox_Fun_SEL_ABI.SelectedIndex = 1;
            comboBox_HistoryMode.SelectedIndex = 0;
        }

        private readonly Form_Chart form_Chart = new Form_Chart();

        private void Form_Closing(object sender, FormClosingEventArgs e) {
        }

        private WBP_Office_Vascular.WBP_Office_Vascular Office_Vascular;

        private void Form1_Load(object sender, EventArgs e) {
            comboBox_Select_Command.SelectedIndex = 0;
            comboBox_DataFormat_DataRead.SelectedIndex = 1;
        }

        private void Office_Vascular_OnReceived(Command command) {

            richTextBox1.BeginInvoke((MethodInvoker)delegate {
                StringBuilder sb = new StringBuilder(richTextBox1.Text);
                switch ((Enum_Command)command.CMD) {
                    case Enum_Command.StartRemoteMeasurement:
                        richTextBox1.Focus();
                        richTextBox1.AppendText(Environment.NewLine);
                        richTextBox1.AppendText("Start Remote Measurement,DataFormat is " + (((Enum_HistoryMode, Enum_DataFormat))command.Data).ToString());
                        sb.Append(richTextBox1.Text);
                        break;

                    case Enum_Command.StopRemoteMeasurement:
                        richTextBox1.AppendText(Environment.NewLine);
                        richTextBox1.AppendText("Stop Remote Measurement");
                        sb.Append(richTextBox1.Text);
                        break;

                    case Enum_Command.RemoteStatus:
                        richTextBox1.AppendText(Environment.NewLine);
                        richTextBox1.AppendText("call back RemoteStatus");
                        GlobalFunction.PrintAllProperties(command, ref sb, append: true);

                        break;

                    case Enum_Command.MeasurementResults:
                        richTextBox1.AppendText(Environment.NewLine);
                        richTextBox1.AppendText("call back MeasurementResults");
                        GlobalFunction.PrintAllProperties(command, ref sb, append: true);

                        break; 
                }
                richTextBox1.Text = sb.ToString();
            });
        }

        private void Office_Vascular_OnDisConnected() {
            try {
                Label_DevicePath.Invoke((MethodInvoker)delegate {
                    Label_DevicePath.Text = "";
                });
                button_Send.Invoke((MethodInvoker)delegate {
                    button_Send.Enabled = false;
                });
            } catch { }
        }

        private void Office_Vascular_OnConnected() {
            Label_DevicePath.Invoke((MethodInvoker)delegate {
                try {
                    Label_DevicePath.Text = Office_Vascular.DevicePath;
                } catch { }
            });
            button_Send.Invoke((MethodInvoker)delegate {
                button_Send.Enabled = true;
            });
        }

        internal void Button_Send_Click(object sender, EventArgs e) {
            (bool Success, Command Command) callback;
            StringBuilder sb = new StringBuilder();
            switch (comboBox_Select_Command.SelectedIndex) {
                case 0:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.dataReadAll());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        comboBox_Index_dataRead.Items.Clear();
                        DRecord listMData = (DRecord)callback.Command.Data;
                        comboBox_Index_dataRead.Items.AddRange(listMData.GetABIWaveIndex().Cast<object>().ToArray());
                        comboBox_Index_dataRead.Items.AddRange(listMData.GetCBPWaveIndex().Cast<object>().ToArray());
                        try {
                            comboBox_Index_dataRead.SelectedIndex = 0;
                        } catch { }
                        GlobalFunction.PrintAllProperties(callback.Command, ref sb);
                    }
                    break;

                case 1:
                    if (comboBox_Index_dataRead.SelectedIndex == -1) {
                        sb.Append("Choose an ID");
                    } else if (comboBox_DataFormat_DataRead.SelectedIndex == -1) {
                        sb.Append("Choose an format");
                    } else {
                        callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.dataRead((int)comboBox_Index_dataRead.SelectedItem, (Enum_DataFormat)(comboBox_DataFormat_DataRead.SelectedIndex)));
                        if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                            sb.Append("NACK");
                        } else if (!callback.Success) {
                            sb.Append("No call back,Please try again");
                        } else {
                            WaveData data = (WaveData)callback.Command.Data;
                            GlobalFunction.PrintAllProperties(callback.Command, ref sb, append: true);
                            form_Chart.chart1.Series.Clear();
                            form_Chart.chart2.Series.Clear();
                            if (data.WaveType == Enum_WaveType.SingleCBP) {
                                form_Chart.chart1.Series.Add("CBP");
                                form_Chart.chart1.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
                                form_Chart.chart1.Series[0].Points.DataBindY(data.Data[0]);

                                form_Chart.chart2.Series.Add("CalCBP");
                                form_Chart.chart2.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
                                form_Chart.chart2.Series[0].Points.DataBindY(data.CalCBP);
                            } else {
                                form_Chart.chart1.Series.Add("R");
                                form_Chart.chart1.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
                                form_Chart.chart1.Series[0].Points.DataBindY(data.Data[0]);
                                form_Chart.chart1.Series.Add("L");
                                form_Chart.chart1.Series[1].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
                                form_Chart.chart1.Series[1].Points.DataBindY(data.Data[1]);
                            }
                        }
                    }
                    break;

                case 2:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.dataClear());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        sb.Append("Memory have clear!");
                    }

                    break;

                case 3:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.userInfoRead());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        UserInfo userInfo = (UserInfo)callback.Command.Data;
                        textBox_NewID.Text = userInfo.UserID;
                        GlobalFunction.PrintAllProperties(callback.Command, ref sb);
                    }
                    break;

                case 4:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.userIDWrite(textBox_NewID.Text));
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    }
                    sb.Append("New ID have writed");

                    break;

                case 5:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.settingRead_BPM());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        Setting_BPM setting_BPM = (Setting_BPM)callback.Command.Data;
                        textBox_Height.Text = setting_BPM.Height.ToString();
                        comboBox_HI_infPressure.SelectedItem = setting_BPM.HI_infPressure.GetString();
                        textBox_IntervalTime.Text = setting_BPM.IntervalTime.ToString();
                        comboBox_AutoMeasureNumber.SelectedItem = setting_BPM.AutoMeasureNumber.ToString();
                        textBox_RestTime.Text = setting_BPM.RestTime.ToString();
                        comboBox_SW_AFib.SelectedItem = setting_BPM.SW_AFib.ToString();
                        comboBox_SW_AMPM.SelectedItem = setting_BPM.SW_AMPM.ToString();
                        comboBox_SW_hide.SelectedItem = setting_BPM.SW_hide.ToString();
                        comboBox_SW_CBP.SelectedItem = setting_BPM.SW_CBP.ToString();
                        comboBox_SW_Kpa.SelectedItem = setting_BPM.SW_Kpa.ToString();
                        comboBox_SW_SEL_silent.SelectedItem = setting_BPM.SW_SEL_silent.ToString();
                        comboBox_SW_AVG_no_include_first.SelectedItem = setting_BPM.SW_AVG_no_include_first.ToString();
                        comboBox_SW_SkipRest.SelectedItem = setting_BPM.SW_SkipRest.ToString();
                        GlobalFunction.PrintAllProperties(callback.Command, ref sb);
                    }
                    break;

                case 6:
                    if (string.IsNullOrEmpty(textBox_Height.Text) || string.IsNullOrEmpty(textBox_IntervalTime.Text) || string.IsNullOrEmpty(textBox_RestTime.Text)) {
                        sb.Append("Please fill Setting_BPM column");
                    } else {
                        Setting_BPM Newsetting_BPM = new Setting_BPM {
                            Height = int.Parse(textBox_Height.Text)
                        };
                        Enum.TryParse((string)comboBox_HI_infPressure.SelectedItem, out Enum_HI_infPressure @enum);
                        Newsetting_BPM.HI_infPressure = @enum;
                        Newsetting_BPM.IntervalTime = int.Parse(textBox_IntervalTime.Text);
                        Newsetting_BPM.AutoMeasureNumber = int.Parse(comboBox_AutoMeasureNumber.SelectedItem.ToString());
                        Newsetting_BPM.RestTime = int.Parse(textBox_RestTime.Text);
                        Newsetting_BPM.SW_AFib = bool.Parse(comboBox_SW_AFib.SelectedItem.ToString());
                        Newsetting_BPM.SW_AMPM = (Enum_AMPM)Enum.Parse(typeof(Enum_AMPM), comboBox_SW_AMPM.SelectedItem.ToString());
                        Newsetting_BPM.SW_hide = bool.Parse(comboBox_SW_hide.SelectedItem.ToString());
                        Newsetting_BPM.SW_CBP = bool.Parse(comboBox_SW_CBP.SelectedItem.ToString());
                        Newsetting_BPM.SW_Kpa = (Enum_PressureUnit)Enum.Parse(typeof(Enum_PressureUnit), comboBox_SW_Kpa.SelectedItem.ToString());
                        Newsetting_BPM.SW_SEL_silent = bool.Parse(comboBox_SW_SEL_silent.SelectedItem.ToString());
                        Newsetting_BPM.SW_AVG_no_include_first = bool.Parse(comboBox_SW_AVG_no_include_first.SelectedItem.ToString());
                        Newsetting_BPM.SW_SkipRest = bool.Parse(comboBox_SW_SkipRest.SelectedItem.ToString());
                        try {
                            callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.settingWrite_BPM(Newsetting_BPM));
                            if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                                sb.Append("NACK");
                            } else if (!callback.Success) {
                                sb.Append("No call back,Please try again");
                            } else {
                                sb.Append("Write Success!");
                            }
                        } catch (Exception ee) {
                            sb.Append(ee.Message);
                        }
                    }
                    break;

                case 7:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.deviceIDRead());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        DeviceID_and_Info deviceID_And_Info = (DeviceID_and_Info)callback.Command.Data;
                        textBox_DeviceID.Text = deviceID_And_Info.ID;
                        comboBox_ConnectType.SelectedIndex = deviceID_And_Info.ConnectType == Enum_ConnectType.USBOnly ? 0 : 1;
                        GlobalFunction.PrintAllProperties(callback.Command, ref sb);
                    }
                    break;

                case 8:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.timeRead());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        DateTime dateTime = (DateTime)callback.Command.Data;
                        dateTimePicker_Device_Time.Value = new DateTime(Math.Max(dateTime.Ticks, new DateTime(1753, 1, 1).Ticks));
                        sb.Append("");
                        if (dateTime.Ticks < new DateTime(1753, 1, 1).Ticks)
                            sb.Append("Datetimepicker can't be set to before 1753/1/1 value,so show 1753/1/1" + Environment.NewLine);
                        sb.AppendLine(dateTime.ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    break;

                case 9:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.timeWrite(dateTimePicker_Device_Time.Value));
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        sb.Append("Time had been sync");
                    }

                    break;

                case 10:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.settingRead_BPM_Function());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        Setting_BPM_Function setting_BPM_Function = (Setting_BPM_Function)callback.Command.Data;
                        comboBox_Fun_SEL_AFIB.SelectedItem = setting_BPM_Function.Fun_SEL_AFIB.ToString();
                        comboBox_Fun_SEL_AMPM.SelectedItem = setting_BPM_Function.Fun_SEL_AMPM.ToString();
                        comboBox_Fun_SEL_Bluetooth.SelectedItem = setting_BPM_Function.Fun_SEL_Bluetooth.ToString();
                        comboBox_Fun_SEL_CBP.SelectedItem = setting_BPM_Function.Fun_SEL_CBP.ToString();
                        comboBox_Fun_SEL_RS232.SelectedItem = setting_BPM_Function.Fun_SEL_RS232.ToString();
                        comboBox_Fun_SEL_UnitKpa.SelectedItem = setting_BPM_Function.Fun_SEL_UnitKpa.ToString();
                        comboBox_Fun_SEL_ABI.SelectedItem = setting_BPM_Function.Fun_SEL_ABI.ToString();
                        comboBox_Fun_SEL_PWV.SelectedItem = setting_BPM_Function.Fun_SEL_PWV.ToString();
                        GlobalFunction.PrintAllProperties(callback.Command, ref sb);
                    }
                    break;

                case 11:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.bluetoothnameRead());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {
                        string s = (string)callback.Command.Data;
                        textBox_BTName.Text = s;
                        sb.Append(s);
                    }
                    break;

                case 12:
                    try {
                        callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.StartRemoteMeasurement((Enum_HistoryMode)comboBox_HistoryMode.SelectedIndex, Enum_DataFormat.No_Raw_Data));
                        if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                            sb.Append("NACK");
                        } else if (!callback.Success) {
                            sb.Append("No call back,Please try again");
                        }
                    } catch (Exception ee) {
                        sb.Append(ee.Message);
                    }
                    break;

                case 13:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.StopRemoteMeasurement());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    }
                    break;


                case 15:
                    callback = Office_Vascular.SendMessage(WBP_Office_Vascular.SendMessage.ToCommand.deviceSNRead());
                    if (callback.Command.CMD == (byte)WBP_Office_Vascular.Enum.Enum_Command.NACK) {
                        sb.Append("NACK");
                    } else if (!callback.Success) {
                        sb.Append("No call back,Please try again");
                    } else {                        
                        string device_SN = (string)callback.Command.Data;
                        textBox_SN.Text = device_SN;
                        sb.Append("SN:" + device_SN);
                    }
                    break;


            }
            richTextBox1.Text = sb.ToString();
        }

        private void Button1_Click(object sender, EventArgs e) {
            form_Chart.Show();
        }

        private void DeviceIDCheck(object sender, KeyPressEventArgs e) {
            try {
                if (e.KeyChar != '\b')
                    Convert.ToInt32(e.KeyChar.ToString(), 16);
            } catch { e.Handled = true; }
        }

        private async void Button_BLE_Click(object sender, EventArgs e) {
            if (!GlobalFunction.WinRT_API_Support) {
                MessageBox.Show("Operating system requires Windows 10 1803 or higher!");
                return;
            }
            Form_BLE_Discover form_BLE_Discover = new Form_BLE_Discover();
            form_BLE_Discover.ShowDialog();
            switch (form_BLE_Discover.BLEAction) {
                case BLEAction.Connect:
                    Office_Vascular.HID_Disconnect();
                    Office_Vascular = new WBP_Office_Vascular.WBP_Office_Vascular(textBox_key.Text, true);

                    Office_Vascular.OnDisConnected += Office_Vascular_OnDisConnected;
                    Office_Vascular.OnReceived += Office_Vascular_OnReceived;
                    var connectionResult = await Office_Vascular.ConnectWithBLE(form_BLE_Discover.BLE_ID, true);
                    if (connectionResult.ErrorMessage == "Device is unreachable (i.e. out of range or shutoff)") {
                        MessageBox.Show("Please check the connection or unpair BLE, both of PC and blood pressure monitor.");
                        Office_Vascular_OnDisConnected();
                    }
                    if (Office_Vascular.Connected) {
                        await Task.Delay(500);
                        try {
                            await Office_Vascular.SendMessageAsync(WBP_Office_Vascular.SendMessage.ToCommand.timeRead());
                        } catch (Exception ee) {
                            if (ee.Message.Contains("0x80650005")) {
                                //PC unpair BLE
                                await PairingHelper.UnpairDeviceAsync(form_BLE_Discover.BLE_ID);
                                MessageBox.Show("Please unpair BLE on blood pressure monitor.");
                                Office_Vascular_OnDisConnected();
                                return;
                            }
                        }
                        Office_Vascular_OnConnected();
                    }
                    break;

                case BLEAction.Disconnect:
                    //await Office_Vascular.SendMessageAsync(WBP_Office_Vascular.SendMessage.ToCommand.bluetoothDisconnect());
                    if (Office_Vascular.ConnectionType == 1)
                        await Office_Vascular?.DisconnectWithBLE();
                    break;

                case BLEAction.Unpair:
                    await PairingHelper.UnpairDeviceAsync(form_BLE_Discover.BLE_ID);
                    break;
            }
        }

        private void Button2_Click(object sender, EventArgs e) {
            try {
                Office_Vascular = new WBP_Office_Vascular.WBP_Office_Vascular(textBox_key.Text);
                Office_Vascular.OnConnected += Office_Vascular_OnConnected;
                Office_Vascular.OnDisConnected += Office_Vascular_OnDisConnected;
                Office_Vascular.OnReceived += Office_Vascular_OnReceived;
                Office_Vascular.InitDeviceWatcher();
                button_BLE.Enabled = true;
                button_Send.Enabled = true;
                textBox_key.Enabled = false;
                (sender as Button).Enabled = false;
            } catch (Exception ee) {
                if (ee.Message == "Key Fail!") {
                    MessageBox.Show("Key Fail!");
                }
            }
        }
    }
}