/*******************************************************************************
* 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.Linq;
using System.Text;

using RPCSupport;
using RPCSupport.Streaming;
using RPCSupport.DataLogging;

namespace HealthSensorPlatform.Model
{
    class DataLogModel : IDataLogModel
    {
        RPCClient rpcClient;
        StreamDataLog streamDataLog;
        EventHandler<PartialArrayIntAvailableEventArgs> onStreamDataHandler; 

        Mission missionSettings;

        public DataLogModel(RPCClient rpcClient)
        {
            this.rpcClient = rpcClient;
        }

        public Mission MissionSettings 
        { 
            get
            {
                return missionSettings;
            }
        }

        public event EventHandler<EventArgs> LogStreamDone;
        public event EventHandler<PartialArrayIntAvailableEventArgs> LogData;

        public void Start()
        {
            onStreamDataHandler = new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData);
            rpcClient.streaming.PartialArrayIntAvailable += onStreamDataHandler;
            streamDataLog = new StreamDataLog(rpcClient);

            streamDataLog.Start();
        }

        public void EraseWrittenSectors()
        {
            ((SerialWrapPipeline)rpcClient.Pipeline).ReadTimeout = 180000;
            rpcClient.DataLogging.EraseWrittenSectors();
            ((SerialWrapPipeline)rpcClient.Pipeline).ReadTimeout = 1000;
        }

        public void MissionStartDefinition()
        {
            rpcClient.DataLogging.MissionStartDefinition();
        }

        public void MissionWrite()
        {
            rpcClient.DataLogging.MissionWrite();
        }

        public void MissionErase()
        {
            rpcClient.DataLogging.EraseMission();
        }

        public void MissionRead()
        {
            rpcClient.DataLogging.MissionRead();

            missionSettings = new Mission();
            // pre cmd
            missionSettings.PreCommand = rpcClient.DataLogging.PreCommand.cmdString;
            // ecg
            missionSettings.EnableEcg = rpcClient.DataLogging.MAX30001_Ecg.IsExistsInDeviceMission();
            if (missionSettings.EnableEcg)
                missionSettings.EcgArgs = rpcClient.DataLogging.MAX30001_Ecg.ToIntArray();
            // pace
            missionSettings.EnablePace = rpcClient.DataLogging.MAX30001_Pace.IsExistsInDeviceMission();
            if (missionSettings.EnablePace)
                missionSettings.PaceArgs = rpcClient.DataLogging.MAX30001_Pace.ToIntArray();
            // bioz
            missionSettings.EnableBioZ = rpcClient.DataLogging.MAX30001_Bioz.IsExistsInDeviceMission();
            if (missionSettings.EnableBioZ)
                missionSettings.BioZArgs = rpcClient.DataLogging.MAX30001_Bioz.ToIntArray();
            // RtoR
            missionSettings.EnableRToR = rpcClient.DataLogging.MAX30001_RtoR.IsExistsInDeviceMission();
            if (missionSettings.EnableRToR)
                missionSettings.RToRArgs = rpcClient.DataLogging.MAX30001_RtoR.ToIntArray();
            // Rbias, FMSTR
            //missionSettings.EnableRBias = rpcClient.DataLogging.MAX30001_Rbias.IsExistsInDeviceMission();
            missionSettings.EnableRBias = missionSettings.EnableRBias | missionSettings.EnableEcg | missionSettings.EnableBioZ | missionSettings.EnableRToR | missionSettings.EnablePace;
            if (missionSettings.EnableRBias)
                missionSettings.RBiasArgs = rpcClient.DataLogging.MAX30001_Rbias_Fmstr.ToIntArray();
            // SpO2
            missionSettings.EnableOpticalSpO2 = rpcClient.DataLogging.MAX30101_SpO2.IsExistsInDeviceMission();
            if (missionSettings.EnableOpticalSpO2)
                missionSettings.SpO2HRModeArgs = rpcClient.DataLogging.MAX30101_SpO2.ToIntArray();
            // HR
            missionSettings.EnableOpticalHR = rpcClient.DataLogging.MAX30101_HR.IsExistsInDeviceMission();
            if (missionSettings.EnableOpticalHR)
                missionSettings.HRModeArgs = rpcClient.DataLogging.MAX30101_HR.ToIntArray();
            // Multi
            missionSettings.EnableOpticalMulti = rpcClient.DataLogging.MAX30101_Multi.IsExistsInDeviceMission();
            if (missionSettings.EnableOpticalMulti)
                missionSettings.MultiModeArgs = rpcClient.DataLogging.MAX30101_Multi.ToIntArray();

            // Temp1
            missionSettings.EnableTemperature1 = rpcClient.DataLogging.MAX31725_1.IsExistsInDeviceMission();
            if (missionSettings.EnableTemperature1)
                missionSettings.Temperature1Parameters = rpcClient.DataLogging.MAX31725_1.ToIntArray();
            // Temp2
            missionSettings.EnableTemperature2 = rpcClient.DataLogging.MAX31725_2.IsExistsInDeviceMission();
            if (missionSettings.EnableTemperature2)
                missionSettings.Temperature2Parameters = rpcClient.DataLogging.MAX31725_2.ToIntArray();
            // Accel
            missionSettings.EnableAccelerometer = rpcClient.DataLogging.LIS2DH.IsExistsInDeviceMission();
            if (missionSettings.EnableAccelerometer)
                missionSettings.AccelerometerParameters = rpcClient.DataLogging.LIS2DH.ToIntArray();
            // Pressure
            missionSettings.EnablePressure = rpcClient.DataLogging.BMP280.IsExistsInDeviceMission();
            if (missionSettings.EnablePressure)
                missionSettings.PressureParameters = rpcClient.DataLogging.BMP280.ToIntArray();


            // post cmd
            missionSettings.PostCommand = rpcClient.DataLogging.PostCommand.cmdString;

        }

        public string[] MissionString()
        {
            string[] missionStrings = rpcClient.DataLogging.MissionStrings();

            List<string> stringList = new List<string>(missionStrings);

            if (stringList[0] == "null")
                stringList.RemoveAt(0);

            if (stringList.Count > 0 && stringList[stringList.Count - 1] == "null")
            {
                stringList.RemoveAt(stringList.Count - 1);
            }

            return stringList.ToArray();
        }

        public void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e)
        {
            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_END_OF_STREAM)
            {
                if (LogStreamDone != null)
                    LogStreamDone(this, e);

                rpcClient.streaming.PartialArrayIntAvailable -= onStreamDataHandler;

            }

            if (LogData != null)
                LogData(this, e);
        }
    }

    public class Mission
    {
        public string PreCommand;
        public bool EnableEcg;
        public int[] EcgArgs;

        public bool EnablePace;
        public int[] PaceArgs;

        public bool EnableBioZ;
        public int[] BioZArgs;

        public bool EnableRToR;
        public int[] RToRArgs;

        public bool EnableRBias;
        public int[] RBiasArgs;

        public bool EnableOpticalSpO2;
        public int[] SpO2HRModeArgs;

        public bool EnableOpticalHR;
        public int[] HRModeArgs;

        public bool EnableOpticalMulti;
        public int[] MultiModeArgs;

        public bool EnableTemperature1;
        public int[] Temperature1Parameters;

        public bool EnableTemperature2;
        public int[] Temperature2Parameters;

        public bool EnablePressure;
        public int[] PressureParameters;

        public bool EnableAccelerometer;
        public int[] AccelerometerParameters;

        public string PostCommand;

        public bool Enable
        {
            get
            {
                return EnableEcg | EnablePace | EnableBioZ | EnableRToR | EnableRBias
                    | EnableOpticalSpO2 | EnableOpticalHR | EnableOpticalMulti
                    | EnableTemperature1 | EnableTemperature2 | EnablePressure | EnableAccelerometer; 
            }
        }
    }
}
