/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
* 
* This software is protected by copyright laws of the United States and
* of foreign countries. This material may also be protected by patent laws
* and technology transfer regulations of the United States and of foreign
* countries. This software is furnished under a license agreement and/or a
* nondisclosure agreement and may only be used or reproduced in accordance
* with the terms of those agreements. Dissemination of this information to
* any party or parties not specified in the license agreement and/or
* nondisclosure agreement is expressly prohibited.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/

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

using HealthSensorPlatform.Model;

namespace HealthSensorPlatform.CustomControls
{
    public partial class DataLoggingView : UserControl, IDeviceView, IDataLoggingView
    {
        /* Fields */
        public GetEcgInitArgs GetEcgInitArgsPointer;
        public GetRToRInitArgs GetRToRInitArgsPointer;
        public GetBioZInitArgs GetBioZInitArgsPointer;
        public GetPaceInitArgs GetPaceInitArgsPointer;
        public GetFMSTRInitArgs GetFMSTRInitArgsPointer;
        public GetHRModeInitArgs GetHRModeInitArgsPointer;
        public GetSpO2HRModeInitArgs GetSpO2HRModeInitArgsPointer;
        public GetMultiModeInitArgs GetMultiModeInitArgsPointer;

        private RPCSupport.RPCClient rpcClient;

        private InitArgs.EcgInitStart ecgArgs;
        private InitArgs.BIOZInitStart bioZArgs;
        private InitArgs.RToRInitStart rToRArgs;
        private InitArgs.PACEInitStart paceArgs;
        private InitArgs.FMSTRInitStart fmstrArgs;
        private InitArgs.HRModeInitStart hrModeArgs;
        private InitArgs.SpO2HRModeInitStart spO2HRModeArgs;
        private InitArgs.MultiModeInitStart multiModeArgs;

        private Model.DataLogModel dataLogModel;
        bool internalUpdate = false;

        /* Constructor */
        public DataLoggingView()
        {
            InitializeComponent();

            dataLogModel = new Model.DataLogModel(rpcClient);
            dataLogModel.LogStreamDone += new EventHandler<EventArgs>(OnLogStreamDone);
        }

        /* Events */
        public event EventHandler<EventArgs> LogDownloadStart;
        public event EventHandler<EventArgs> MissionWrite;
        public event EventHandler<EventArgs> MissionRead;
        public event EventHandler<EventArgs> MissionErase;

        /* Properties */
        public RPCSupport.RPCClient RPCClient
        {
            set
            {
                rpcClient = value;
            }
        }

        public bool Connected { get; set; }

        public InitArgs.EcgInitStart EcgArgs
        {
            get
            {
                return ecgArgs;
            }
            set
            {
                ecgArgs = value;
                if (ecgArgs != null)
                    tbEcgParameters.Text = ecgArgs.ToCommandString();
                else
                    tbEcgParameters.Text = "";
            }
        }
        public InitArgs.BIOZInitStart BioZArgs
        {
            get
            {
                return bioZArgs;
            }
            set
            {
                bioZArgs = value;
                if (bioZArgs != null)
                    tbBiozParameters.Text = bioZArgs.ToCommandString();
                else
                    tbBiozParameters.Text = "";
            }
        }
        public InitArgs.RToRInitStart RToRArgs
        {
            get
            {
                return rToRArgs;
            }
            set
            {
                rToRArgs = value;
                if (rToRArgs != null)
                    tbRtoRParameters.Text = rToRArgs.ToCommandString();
                else
                    tbRtoRParameters.Text = "";
            }
        }
        public InitArgs.PACEInitStart PaceArgs
        {
            get
            {
                return paceArgs;
            }
            set
            {
                paceArgs = value;
                if (paceArgs != null)
                    tbPaceParameters.Text = paceArgs.ToCommandString();
                else
                    tbPaceParameters.Text = "";
            }
        }
        public InitArgs.FMSTRInitStart FMSTRArgs
        {
            get
            {
                return fmstrArgs;
            }
            set
            {
                fmstrArgs = value;
                if (fmstrArgs != null && (ecgArgs != null || bioZArgs != null || rToRArgs != null || paceArgs != null))
                    tbFMSTRParameters.Text = fmstrArgs.ToCommandString();
                else
                    tbFMSTRParameters.Text = "";
            }
        }
        public InitArgs.SpO2HRModeInitStart SpO2HRModeArgs
        {
            get
            {
                return spO2HRModeArgs;
            }
            set
            {
                spO2HRModeArgs = value;
                if (spO2HRModeArgs == null)
                    tbSpO2Parameters.Text = "";
                else 
                    tbSpO2Parameters.Text = spO2HRModeArgs.ToCommandString();
            }
        }
        public InitArgs.HRModeInitStart HRModeArgs
        {
            get
            {
                return hrModeArgs;
            }
            set
            {
                hrModeArgs = value;
                if (hrModeArgs == null)
                    tbHRParameters.Text = "";
                else
                    tbHRParameters.Text = hrModeArgs.ToCommandString();
            }
        }
        public InitArgs.MultiModeInitStart MultiModeArgs
        {
            get
            {
                return multiModeArgs;
            }
            set
            {
                multiModeArgs = value;
                if (multiModeArgs != null)
                    tbMultiParameters.Text = multiModeArgs.ToCommandString();
                else
                    tbMultiParameters.Text = "";
            }
        }

        /* Setters and Getters attempting to disconnect the GUI controls from the internal code */
        public bool EnableEcg 
        { 
            get 
            { 
                return ckbxEcg.Checked; 
            } 
            set
            {
                ckbxEcg.Checked = value;
            }
        }
        public bool EnablePace 
        { 
            get 
            { 
                return ckbxPace.Checked; 
            } 
            set
            {
                ckbxPace.Checked = value;
            }
        }
        public bool EnableBioz 
        { 
            get 
            { 
                return ckbxBioz.Checked; 
            } 
            set
            {
                ckbxBioz.Checked = value;
            }
        }
        public bool EnableRToR 
        { 
            get 
            { 
                return ckbxRtoR.Checked; 
            } 
            set
            {
                ckbxRtoR.Checked = value;
            }
        }
        public bool EnableFMSTR
        {
            get
            {
                return EnableEcg || EnableBioz || EnablePace || EnableRToR;
            }
        }
        public bool EnableOpticalSpO2 
        { 
            get 
            {
                return (string)cboOpticalMode.SelectedItem == "SpO2";
            } 
            set
            {
                if (value)
                    cboOpticalMode.SelectedItem = "SpO2";
            }
        }
        public bool EnableOpticalHR 
        { 
            get 
            {
                return (string)cboOpticalMode.SelectedItem == "HR";
            } 
            set
            {
                if (value)
                    cboOpticalMode.SelectedItem = "HR";
            }
        }
        public bool EnableOpticalMulti 
        { 
            get 
            {
                return (string)cboOpticalMode.SelectedItem == "Multi";
            }
            set
            {
                if (value)
                    cboOpticalMode.SelectedItem = "Multi";
            }
        }
        public bool EnableTemperature1 
        { 
            get 
            { 
                return ckbxTemp1.Checked; 
            } 
            set
            {
                ckbxTemp1.Checked = value;
            }
        }
        public bool EnableTemperature2 
        { 
            get 
            { 
                return ckbxTemp2.Checked; 
            } 
            set
            {
                ckbxTemp2.Checked = value;
            }
        }
        public bool EnableAccelerometer 
        { 
            get 
            { 
                return ckbxAccel.Checked; 
            } 
            set
            {
                ckbxAccel.Checked = value;
            }
        }
        public bool EnablePressure 
        { 
            get 
            { 
                return ckbxPressure.Checked; 
            } 
            set
            {
                ckbxPressure.Checked = value;
            }
        }

        public int AccelSampleRate
        {
            get
            {
                return Int32.Parse((string)cboAccelSampleRate.SelectedItem);
            }
        }

        /* Delegates */
        public delegate InitArgs.EcgInitStart GetEcgInitArgs();
        public delegate InitArgs.RToRInitStart GetRToRInitArgs();
        public delegate InitArgs.BIOZInitStart GetBioZInitArgs();
        public delegate InitArgs.PACEInitStart GetPaceInitArgs();
        public delegate InitArgs.FMSTRInitStart GetFMSTRInitArgs();
        public delegate InitArgs.HRModeInitStart GetHRModeInitArgs();
        public delegate InitArgs.SpO2HRModeInitStart GetSpO2HRModeInitArgs();
        public delegate InitArgs.MultiModeInitStart GetMultiModeInitArgs();

        public delegate void LoggingParametersHandler(object sender, EventArgs e);

        /* Events */
        public event LoggingParametersHandler LoggingParametersChanged;

        private void LoggingView_Load(object sender, EventArgs e)
        {
            cboOpticalMode.SelectedIndex = 0;
            cboAccelSampleRate.SelectedIndex = 0;
        }

        private void btnRead_Click(object sender, EventArgs e)
        {
            if (MissionRead != null)
                MissionRead(this, e);

            if (Connected)
            {
                if (LoggingParametersChanged != null)
                    LoggingParametersChanged(this, EventArgs.Empty);

                //btnWrite.Enabled = false;
            }
        }

        private void btnErase_Click(object sender, EventArgs e)
        {
            if (MissionErase != null)
            {
                MissionErase(this, e);
            }
        }

        private void btnWrite_Click(object sender, EventArgs e)
        {
            if (MissionWrite != null)
            {
                MissionWrite(this, e);
            }
        }

        private void btnTestMission_Click(object sender, EventArgs e)
        {
            rpcClient.DataLogging.TestMission();
        }

        private void btnTestWriteLogMemory_Click(object sender, EventArgs e)
        {
            //Process
            //rpcClient.DataLogging.TestWriteLog();
        }

        private void btnTestReadLogMemory_Click(object sender, EventArgs e)
        {
            rpcClient.DataLogging.TestReadLog();
        }

        private void btnBulkErase_Click(object sender, EventArgs e)
        {
            rpcClient.DataLogging.TestBulkErase();
        }

        private void btnLogSectorsErase_Click(object sender, EventArgs e)
        {
            rpcClient.DataLogging.TestLogSectorsErase();
        }

        private int[] ParseHexString(String hexStr)
        {
            int val;
            List<int> intList = new List<int>();
            String[] strings = hexStr.Split(new char[] { ' ' });
            foreach (String str in strings)
            {
                if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
                {
                    intList.Add(val);
                }
                else
                {
                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
                }
            }
            return intList.ToArray();
        }

        /// <summary>
        /// Write GUI elements to flash
        /// Call ValidateGuiElements() to verify user input acceptable before calling ProcessGuiElements()
        /// </summary>
        public bool ProcessGuiElements()
        {
            int[] temperature1 = new int[1] {10};
            int[] temperature2 = new int[1] {10};
            int[] barometer = new int[1];

            if (EnableTemperature1)
                temperature1[0] = Int32.Parse(txtTemp1SampleTime.Text.Trim());
            if (EnableTemperature2)
                temperature2[0] = Int32.Parse(txtTemp2SampleTime.Text.Trim());
            if (EnablePressure)
                barometer[0] = Int32.Parse(txtPressureSampleTime.Text.Trim());

            // Pre Commands
            rpcClient.DataLogging.PreCommand.Define(tbPreCmd.Text.Trim());
            rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.PreCommand);
            // ecg
            if (EnableEcg)
            {
                InitArgs.EcgInitStart ecgArgs = GetEcgInitArgsPointer();
                //rpcClient.DataLogging.MAX30001_Ecg.AssignByIntArray(ParseHexString(tbEcgParameters.Text));
                rpcClient.DataLogging.MAX30001_Ecg.AssignByValue(
                    1, //ecgArgs.En_ecg,
                    ecgArgs.Openp,
                    ecgArgs.Openn,
                    ecgArgs.Pol,
                    ecgArgs.Calp_sel,
                    ecgArgs.Caln_sel,
                    ecgArgs.E_fit,
                    ecgArgs.Rate,
                    ecgArgs.Gain,
                    ecgArgs.Dhpf,
                    ecgArgs.Dlpf
                );
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Ecg);
            }
            // pace
            if (EnablePace)
            {
                InitArgs.PACEInitStart paceArgs = GetPaceInitArgsPointer();
                //rpcClient.DataLogging.MAX30001_Pace.AssignByIntArray(ParseHexString(tbPaceParameters.Text));
                rpcClient.DataLogging.MAX30001_Pace.AssignByValue(
                    1,//paceArgs.En_pace,
                    paceArgs.Clr_pedge,
                    paceArgs.Pol,
                    paceArgs.Gn_diff_off,
                    paceArgs.Gain,
                    paceArgs.Aout_lbw,
                    paceArgs.Aout,
                    paceArgs.Dacp,
                    paceArgs.Dacn
                 );
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Pace);
            }
            // bioz
            if (EnableBioz)
            {
                InitArgs.BIOZInitStart biozArgs = GetBioZInitArgsPointer();
                //rpcClient.DataLogging.MAX30001_Bioz.AssignByIntArray(ParseHexString(tbBiozParameters.Text));
                rpcClient.DataLogging.MAX30001_Bioz.AssignByValue(
                    1, //biozArgs.En_bioz,
                    biozArgs.Openp,
                    biozArgs.Openn,
                    biozArgs.Calp_sel,
                    biozArgs.Caln_sel,
                    biozArgs.CG_mode,
                    biozArgs.B_fit,
                    biozArgs.Rate,
                    biozArgs.Ahpf,
                    biozArgs.Ext_rbias,
                    biozArgs.Gain,
                    biozArgs.Dhpf,
                    biozArgs.Dlpf,
                    biozArgs.Fcgen,
                    biozArgs.Cgmon,
                    biozArgs.Cgmag,
                    biozArgs.Phoff
                );
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Bioz);
            }
            // RtoR
            if (EnableRToR)
            {
                InitArgs.RToRInitStart rtorArgs = GetRToRInitArgsPointer();
                //rpcClient.DataLogging.MAX30001_RtoR.AssignByIntArray(ParseHexString(tbRtoRParameters.Text));
                rpcClient.DataLogging.MAX30001_RtoR.AssignByValue(
                    1, //rtorArgs.En_rtor,
                    rtorArgs.Wndw,
                    rtorArgs.Gain,
                    rtorArgs.Pavg,
                    rtorArgs.Ptsf,
                    rtorArgs.Hoff,
                    rtorArgs.Ravg,
                    rtorArgs.Rhsf,
                    rtorArgs.Clr_rrint
                );
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_RtoR);
            }
            // SpO2
            if (EnableOpticalSpO2)
            {
                rpcClient.DataLogging.MAX30101_SpO2.AssignByIntArray(ParseHexString(tbSpO2Parameters.Text));
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30101_SpO2);
            }
            // HR
            if (EnableOpticalHR)
            {
                rpcClient.DataLogging.MAX30101_HR.AssignByIntArray(ParseHexString(tbHRParameters.Text));
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30101_HR);
            }
            // Multi
            if (EnableOpticalMulti)
            {
                rpcClient.DataLogging.MAX30101_Multi.AssignByIntArray(ParseHexString(tbMultiParameters.Text));
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30101_Multi);
            }
            // Temp1
            if (EnableTemperature1)
            {
                rpcClient.DataLogging.MAX31725_1.AssignByIntArray(temperature1);
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX31725_1);
            }
            // Temp2
            if (EnableTemperature2)
            {
                rpcClient.DataLogging.MAX31725_2.AssignByIntArray(temperature2);
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX31725_2);
            }
            // Accel
            if (EnableAccelerometer)
            {
                rpcClient.DataLogging.LIS2DH.AssignByIntArray(new int[] {cboAccelSampleRate.SelectedIndex + 1, 15}); // FIFO depth is second parameter
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.LIS2DH);
            }
            // Pressure
            if (EnablePressure)
            {
                rpcClient.DataLogging.BMP280.AssignByIntArray(barometer);
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.BMP280);
            }

            // add Rbias if we are using any of the MAX30001 commands
            if (EnableEcg || EnableBioz || EnablePace || EnableRToR)
            {
                //rpcClient.DataLogging.MAX30001_Rbias.Define("/MAX30001/Rbias_FMSTR_Init 01 02 01 01 00");
                rpcClient.DataLogging.MAX30001_Rbias_Fmstr.AssignByIntArray(ParseHexString(tbFMSTRParameters.Text));
                //rpcClient.DataLogging.MAX30001_Rbias.Define("/MAX30001/Rbias_FMSTR_Init " + tbFMSTRParameters.Text);
                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Rbias_Fmstr);
            }
            // Post Commands
            rpcClient.DataLogging.PostCommand.Define(tbPostCmd.Text.Trim());
            rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.PostCommand);

            return true;
        }

        public bool ValidateGuiElements()
        {
            const int MaxTime = 1000; // TODO Ask Jerry to calculate the 16 bit timer limit
            const int MinTime = 0;
            const int MinRecommendedTempTime = 10;
            int[] temperature1 = new int[1] { 10 };
            int[] temperature2 = new int[1] { 10 };
            int[] barometer = new int[1];

            try
            {
                if (EnableTemperature1)
                    temperature1[0] = Int32.Parse(txtTemp1SampleTime.Text.Trim());
                if (EnableTemperature2)
                    temperature2[0] = Int32.Parse(txtTemp2SampleTime.Text.Trim());
                if (EnablePressure)
                    barometer[0] = Int32.Parse(txtPressureSampleTime.Text.Trim());
                // TODO Limit Max and Min Range
                if (temperature1[0] > MaxTime || temperature2[0] > MaxTime || barometer[0] > MaxTime)
                {
                    MessageBox.Show("Time value cannot be larger than " + MaxTime);
                }
                else if (temperature1[0] < MinTime || temperature2[0] < MinTime || barometer[0] < MinTime)
                {
                    MessageBox.Show("Time value cannot be less than " + MinTime);
                }
                else if (temperature1[0] < MinRecommendedTempTime || temperature2[0] < MinRecommendedTempTime)
                {
                    MessageBox.Show("The recommended temperature sample period is >" + MinRecommendedTempTime + " seconds due to self heating effects.", "Warning");
                }
            }
            catch (Exception)
            {
                if (EnableTemperature1 || EnableTemperature2 || EnablePressure)
                {
                    MessageBox.Show("Temperature 1 & 2 and Barometer must contain only digits", "Sample Rates");
                    return false;
                }
            }

            return true;
        }


        /// <summary>
        /// Update GUI with data read from flash
        /// </summary>
        public void UpdateGuiElements(Mission missionSettings)
        {
            internalUpdate = true;

            // Set optical state to none
            cboOpticalMode.SelectedIndex = 0;

            // pre cmd
            tbPreCmd.Text = missionSettings.PreCommand;
            // ecg
            EnableEcg = missionSettings.EnableEcg;
            if (EnableEcg)
                EcgArgs = EcgArgs.FromIntArray(missionSettings.EcgArgs);
            else
                EcgArgs = null;
            // pace
            EnablePace = missionSettings.EnablePace;
            if (EnablePace)
                PaceArgs = PaceArgs.FromIntArray(missionSettings.PaceArgs);
            else
                PaceArgs = null;
            // bioz
            EnableBioz = missionSettings.EnableBioZ;
            if (EnableBioz)
                BioZArgs = BioZArgs.FromIntArray(missionSettings.BioZArgs);
            else
                BioZArgs = null;
            // RtoR
            EnableRToR = missionSettings.EnableRToR;
            if (EnableRToR)
                RToRArgs = RToRArgs.FromIntArray(missionSettings.RToRArgs);
            else
                RToRArgs = null;
            // Rbias, FMSTR
            if (EnableFMSTR && missionSettings.EnableRBias) // Only applies when OT90 is used
                FMSTRArgs = FMSTRArgs.FromIntArray(missionSettings.RBiasArgs);
            else
                FMSTRArgs = null;
            // SpO2, HR
            EnableOpticalSpO2 = missionSettings.EnableOpticalSpO2;
            if (EnableOpticalSpO2)
                SpO2HRModeArgs = SpO2HRModeArgs.FromIntArray(missionSettings.SpO2HRModeArgs);
            else
                SpO2HRModeArgs = null;
            EnableOpticalHR = missionSettings.EnableOpticalHR;
            if (EnableOpticalHR)
                HRModeArgs = HRModeArgs.FromIntArray(missionSettings.HRModeArgs);
            else
                HRModeArgs = null;
            // Multi
            EnableOpticalMulti = missionSettings.EnableOpticalMulti;
            if (EnableOpticalMulti)
                MultiModeArgs = MultiModeArgs.FromIntArray(missionSettings.MultiModeArgs);
            else
                MultiModeArgs = null;

            if (EnableOpticalSpO2)
            {
                cboOpticalMode.SelectedItem = "SpO2";
            }
            else if (EnableOpticalHR)
            {
                cboOpticalMode.SelectedItem = "HR";
            }
            else if (EnableOpticalMulti)
            {
                cboOpticalMode.SelectedItem = "Multi";
            }
            else
            {
                cboOpticalMode.SelectedItem = "None";
            }

            /* These Parameters to not effect the other GUI tabs, thus are not accessible in a property field */
            // Temp1
            EnableTemperature1 = missionSettings.EnableTemperature1;
            txtTemp1SampleTime.Text = EnableTemperature1 ? missionSettings.Temperature1Parameters[0].ToString() : "";
            // Temp2
            EnableTemperature2 = missionSettings.EnableTemperature2;
            txtTemp2SampleTime.Text = EnableTemperature2 ? missionSettings.Temperature2Parameters[0].ToString() : "";
            // Accel
            EnableAccelerometer = missionSettings.EnableAccelerometer;
            cboAccelSampleRate.SelectedIndex = EnableAccelerometer ? missionSettings.AccelerometerParameters[0] - 1 : 0;
            // Pressure
            EnablePressure = missionSettings.EnablePressure;
            txtPressureSampleTime.Text = EnablePressure ? missionSettings.PressureParameters[0].ToString() : "";
            // post cmd
            tbPostCmd.Text = missionSettings.PostCommand;

            internalUpdate = false;
        }

        /// <summary>
        /// Update the logging parameters
        /// </summary>
        public void UpdateArgs()
        {
            updateArgsOT90();
            updateArgsOS24();
        }

        private void updateArgsOT90()
        {
            InitArgs.EcgInitStart eargs;
            InitArgs.BIOZInitStart bargs;
            InitArgs.RToRInitStart rargs;
            InitArgs.PACEInitStart pargs;
            InitArgs.FMSTRInitStart fargs;

            //btnWrite.Enabled = true;

            // Override enable bit since if command is being sent, this should be set to 1
            // based the data logging enable bit and not the GUI tab enable controls
            if (GetEcgInitArgsPointer != null)
            {
                eargs = GetEcgInitArgsPointer();
                eargs.En_ecg = 1;  

                EcgArgs = eargs;
            }

            if (GetBioZInitArgsPointer != null)
            {
                bargs = GetBioZInitArgsPointer();
                bargs.En_bioz = 1;  

                BioZArgs = bargs;
            }

            if (GetRToRInitArgsPointer != null)
            {
                rargs = GetRToRInitArgsPointer();
                rargs.En_rtor = 1;

                RToRArgs = rargs;
            }

            if (GetPaceInitArgsPointer != null)
            {
                pargs = GetPaceInitArgsPointer();
                pargs.En_pace = 1;

                PaceArgs = pargs;
            }

            if (GetFMSTRInitArgsPointer != null)
            {
                fargs = GetFMSTRInitArgsPointer();

                FMSTRArgs = fargs;
            }

        }

        private void updateArgsOS24()
        {
            if (GetSpO2HRModeInitArgsPointer != null)
            {
                SpO2HRModeArgs = GetSpO2HRModeInitArgsPointer();
            }

            if (GetHRModeInitArgsPointer != null)
            {
                HRModeArgs = GetHRModeInitArgsPointer();
            }

            if (GetMultiModeInitArgsPointer != null)
            {
                MultiModeArgs = GetMultiModeInitArgsPointer();
            }

        }

        public void PaceFunction(bool enable)
        {
            ckbxPace.Enabled = enable;
            lblPace.Enabled = enable;
            tbPaceParameters.Enabled = enable;
        }

        public void BioZFunction(bool enable)
        {
            ckbxBioz.Enabled = enable;
            lblBioZ.Enabled = enable;
            tbBiozParameters.Enabled = enable;
        }

        private void btnAdvanced_Click(object sender, EventArgs e)
        {
            grpParameters.Visible = !grpParameters.Visible;
            grpPrePostCommands.Visible = !grpPrePostCommands.Visible;
        }

        private void cboOpticalMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;

            if (internalUpdate == true)
                return;

            internalUpdate = true;

            if ((string)cbo.SelectedItem == "SpO2")
            {
                EnableOpticalSpO2 = true;
                EnableOpticalHR = false;
                EnableOpticalMulti = false;
            }
            else if ((string)cbo.SelectedItem == "HR")
            {
                EnableOpticalSpO2 = false;
                EnableOpticalHR = true;
                EnableOpticalMulti = false;
            }
            else if ((string)cbo.SelectedItem == "Multi")
            {
                EnableOpticalSpO2 = false;
                EnableOpticalHR = false;
                EnableOpticalMulti = true;
            }
            else
            {
                EnableOpticalSpO2 = false;
                EnableOpticalHR = false;
                EnableOpticalMulti = false;
            }

            updateArgsOS24();

            internalUpdate = false;
        }

        private void btnSaveToFile_Click(object sender, EventArgs e)
        {
            if (LogDownloadStart != null)
                LogDownloadStart(this, e);

            //btnWrite.Enabled = false;

        }

        private void OnLogStreamDone(object sender, EventArgs e)
        {
            if (LogDownloadStart != null)
                LogDownloadStart(this, e);
        }

        private void ckbxBioz_CheckedChanged(object sender, EventArgs e)
        {
            if (ckbxEcg.Checked)
                ckbxRtoR.Enabled = true;

            if (ckbxEcg.Checked == false) 
            {
                if (ckbxRtoR.Checked == true)
                    ckbxRtoR.Checked = false;

                ckbxRtoR.Enabled = false;
            }

            MaximStyle.MaximCheckBox cbo = (MaximStyle.MaximCheckBox)sender;
            if (cbo.Checked)
                updateArgsOT90();
        }

    }
}
