/*******************************************************************************
* 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 HealthSensorPlatform.View;
using HealthSensorPlatform.CustomControls;

using RPCSupport.Streaming;

namespace HealthSensorPlatform.Presenter
{
    public class OpticalFileLogPresenter
    {
        IRawFileLogView optical;
        IRawFileLogView accel;
        HspForm mainForm;
        OpticalView opticalView;

        string logFileDirectory = null;

        int ppgCount = 0;
        int accelCount = 0;

        public OpticalFileLogPresenter(RPCSupport.RPCClient rpcClient, HspForm mainForm, OpticalView opticalView, IRawFileLogView optical, IRawFileLogView accel)
        {
            this.optical = optical;
            this.accel = accel;
            this.mainForm = mainForm;
            this.opticalView = opticalView;

            rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData);
            mainForm.OpticalFileLogEnable += new EventHandler<EnableEventArgs>(OnFileLogEnable);
            //opticalView.StreamingStartStop += new OpticalView.StreamingStartStopEventHandler(OnStreamingStartStop);
            opticalView.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamingStartStop);
        }

        public void ProcessOptical(int[] red, int[] ir, int[] green)
        {
            double[] time = new double[red.Length];

            for (int i = 0; i < time.Length; i++ )
            {
                time[i] = ppgCount / (double)opticalView.OpticalSampleRate;
                ppgCount++;
            }

            optical.DisplayPpg(time, new int[][] { red, ir, green });
        }

        public void ProcessXYZ(int[] x, int[] y, int[] z)
        {
            int[] decimalFormatX;
            int[] decimalFormatY;
            int[] decimalFormatZ;
            double[] time = new double[x.Length];

            decimalFormatX = ConvertXYZBinary(x);
            decimalFormatY = ConvertXYZBinary(y);
            decimalFormatZ = ConvertXYZBinary(z);

            for (int i = 0; i < time.Length; i++ )
            {
                time[i] = accelCount / (double)opticalView.AccelSampleRate;
                accelCount++;
            }

            accel.DisplayXYZ(time, new int[][] { decimalFormatX, decimalFormatY, decimalFormatZ });
        }

        public static int[] ConvertXYZBinary(int[] data)
        {
            int[] decimalFormat = new int[data.Length];

            for (int i = 0; i < data.Length; i++)
            {
                if (data[i] > 0x8000)
                    decimalFormat[i] = data[i] - 0x10000;
                else
                    decimalFormat[i] = data[i];
            }

            return decimalFormat;
        }

        public void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e)
        {
            if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
            {
                if (optical.Enable)
                    ProcessOptical(e.array1, e.array2, e.array3);
            }
            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_LIS2DH)
            {
                if (accel.Enable)
                    ProcessXYZ(e.array1, e.array2, e.array3);
            }
        }

        void OnFileLogEnable(object sender, EnableEventArgs e)
        {
            optical = new RawFileLogView();
            accel = new RawFileLogView();

            if (logFileDirectory != null)
            {
                optical.FileDirectory = logFileDirectory;
                //accel.FileDirectory = logFileDirectory;
            }

            if (e.Enable && e.Stream == StreamType.Optical && optical.SelectCSVFile("hsp-optical"))
            {
                accel.FileDirectory = optical.FileDirectory;
                if (accel.SelectCSVFile("hsp-accel"))
                {
                    mainForm.OpticalLogFileItem(true);
                    optical.Enable = true;
                    accel.Enable = true;
                    logFileDirectory = optical.FileDirectory;
                }
            }
            else
            {
                mainForm.OpticalLogFileItem(false);
                optical.Enable = false;
                accel.Enable = false;
            }
        }

        void OnStreamingStartStop(object sender, StreamingStartStopEventArgs e)
        {
            if (e.state == true)
            {
                View.FileLogView.FileLogHeader fileLogHeader = new View.FileLogView.FileLogHeader();
                ppgCount = 0;
                accelCount = 0;

                if (optical.Enable == true)
                {
                    optical.WriteLine(opticalView.SettingsString());
                    optical.WriteLine(fileLogHeader.Optical);
                }
                if (accel.Enable == true)
                {
                    accel.WriteLine(opticalView.AccelSettingString());
                    accel.WriteLine(fileLogHeader.Accelerometer);

                    // Try to have "0" be the same on both files
                    optical.StreamStartStop();
                    accel.StreamStartStop(); 
                }
                
            }
            else
            {
                optical.Enable = false;
                accel.Enable = false;

                mainForm.LogFileItem(StreamType.Optical, false);
            }
        }
    }
}
