/*******************************************************************************
* 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 System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using MAX30205EVKit.Model;
using MAX30205EVKit.View;

using HealthSensorPlatform.CustomControls;
using HealthSensorPlatform;

using Maxim.Utility;

namespace MAX30205EVKit.Presenter
{
    class TemperaturePresenter 
    {
        ITemperatureModel[] model;
        ITemperatureView view;
        IDeviceView connected;
        //IFileLogView fileLogView;

        TemperatureValue temperature;
        TemperatureValue overTemperature;
        TemperatureValue hystersis;

        //bool firstTime = true;
        //double time = 0.0;

        public TemperaturePresenter(ITemperatureModel[] model, IDeviceView connected, ITemperatureView view) 
        {
            this.model = model;
            this.view = view;
            this.connected = connected;

            //this.fileLogView = fileLogView;

            view.ReadAll += new EventHandler<EventArgs>(OnReadAll);
            view.RequestReadTemperature += new EventHandler<EventArgs>(OnReadTemperature);
            view.OverTemperatureChanged += new EventHandler<TemperatureEventArgs>(OnOverTemperatureChanged);
            view.HystersisChanged += new EventHandler<TemperatureEventArgs>(OnHystersisChanged);
            view.WriteRegister += new EventHandler<WriteRegisterEventArgs>(OnWriteRegister);
            view.DataFormatChanged += new EventHandler<DataFormatEventArgs>(OnDataFormatChanged);
        }

        /*
        public TemperaturePresenter(ITemperatureModel model, IDeviceView connected, ITemperatureView view, IFileLogView fileLogView)
        {
            this.model = model;
            this.view = view;
            this.connected = connected;

            this.fileLogView = fileLogView;

            view.ReadAll += new EventHandler<EventArgs>(OnReadAll);
            view.RequestReadTemperature += new EventHandler<EventArgs>(OnReadTemperature);
            view.OverTemperatureChanged += new EventHandler<TemperatureEventArgs>(OnOverTemperatureChanged);
            view.HystersisChanged += new EventHandler<TemperatureEventArgs>(OnHystersisChanged);
            view.WriteRegister += new EventHandler<WriteRegisterEventArgs>(OnWriteRegister);

        } 
        */

        public void WriteRegister(int index, int register, int data)
        {
            if (connected.Connected)
                model[index].RegWrite(register, data);
        }

        public void OnReadAll(object sender, EventArgs e)
        {
            int temperatureHex;
            int configuration;
            int hystersisHex;
            int overTemperatureHex;


            if (connected.Connected)
            {
                for (int i = 0; i < model.Length; i++)
                {
                    temperatureHex = model[i].RegRead(0x00);
                    configuration = model[i].RegRead(0x01);
                    hystersisHex = model[i].RegRead(0x02);
                    overTemperatureHex = model[i].RegRead(0x03);

                    temperature = new TemperatureValue(temperatureHex, model[i].DataFormat);
                    overTemperature = new TemperatureValue(overTemperatureHex, model[i].DataFormat);
                    hystersis = new TemperatureValue(hystersisHex, model[i].DataFormat);

                    view.DisplayTemperature(i, temperature);
                    view.DisplayConfigurationRegister(i, configuration);
                    view.DisplayOverTemperature(i, overTemperature);
                    view.DisplayHysteresis(i, hystersis);
                }
            }
        }

        public void OnDataFormatChanged(object sender, DataFormatEventArgs e)
        {
            int hysteresisHex = model[e.Index].Registers[0x02];
            int overtemperature = model[e.Index].Registers[0x03];

            if (connected.Connected)
            {
                overTemperature = new TemperatureValue(overtemperature, e.DataFormat);
                hystersis = new TemperatureValue(hysteresisHex, e.DataFormat);

                view.DisplayOverTemperature(e.Index, overTemperature);
                view.DisplayHysteresis(e.Index, hystersis);
            }
        }

        void OnReadTemperature(object sender, EventArgs e)
        {
            if (connected.Connected)
            {
                for (int i = 0; i < model.Length; i++)
                {
                    int configuration = model[i].RegRead(0x01);

                    //model[i].RegWrite(0x01, configuration | 0x81);
                    model[i].RegWrite(0x01, configuration | 0x80);
                    System.Threading.Thread.Sleep(50);
                    int temp = model[i].RegRead(0x00);

                    TemperatureValue tempValue = new TemperatureValue(temp, model[i].DataFormat);
                    view.DisplayTemperature(i, tempValue);

                    //If user chooses to log Temperature, write lines to CSV
                    WriteTempToFileLog(tempValue);
                }
            }
        }



        void OnOverTemperatureChanged(object sender, TemperatureEventArgs e)
        {
            if (!IsWithinRange(e.Temperature.ToString(), model[e.Index].DataFormat))
                view.DisplayError(e.Control, "Temperature Out of Range");
            else
            {
                overTemperature = new TemperatureValue(e.Temperature, model[e.Index].DataFormat);

                view.DisplayOverTemperature(e.Index, overTemperature);

                if (connected.Connected)
                    model[e.Index].RegWrite(0x03, overTemperature.TemperatureHex);
            }
            
        }

        void OnHystersisChanged(object sender, TemperatureEventArgs e)
        {
            if (!IsWithinRange(e.Temperature.ToString(), model[e.Index].DataFormat))
                view.DisplayError(e.Control, "Temperature Out of Range");
            else
            {
                hystersis = new TemperatureValue(e.Temperature, model[e.Index].DataFormat);

                view.DisplayHysteresis(e.Index, hystersis);

                if (connected.Connected)
                    model[e.Index].RegWrite(0x02, hystersis.TemperatureHex);
            }

            
        }

        void OnWriteRegister(object sender, WriteRegisterEventArgs e)
        {
            WriteRegister(e.Index, e.Register, e.Data);
        }

        void WriteTempToFileLog(TemperatureValue tempValue)
        {
            /*
            if (fileLogView.Enable)
            {
                if (firstTime)
                {
                    firstTime = false;
                    fileLogView.WriteLine("Time (s), Temperature (°C)");
                }
                else
                {
                    time = time + view.RefreshRate;
                }
                var temp = Math.Round(tempValue.TemperatureC, 3);
                fileLogView.WriteTemp(time, temp);
            }
             */
        }

        bool IsWithinRange(string str, bool dataFormat)
        {
            double temp;
            if (Double.TryParse(str, out temp))
            {
                if (!dataFormat)

                    return (temp >= -128.00) && (temp < 127.997);

                return (temp >= -64.00) && (temp < 191.997);
            }

            return false;
        }

        /*        void OnTimerTick(object sender, ElapsedEventArgs e)
                {
                    if (connected.Connected)
                    {
                        int temperature;

                        model.RegWrite(0x01, model.Registers[0x01] | 0x81);
                        System.Threading.Thread.Sleep(50);
                        temperature = model.RegRead(0x00);

                        TemperatureValue tempValue = new TemperatureValue(temperature, model.DataFormat);
                        view.DisplayTemperature(0, tempValue);
                    }
                }*/



        /*        double hexToTemperature(int hex, bool dataFormat, bool unitCelsius)
                {
                    int normalCode;
                    int rawCode = hex;
                    double celsius;

                    if (rawCode > 0x7fff)
                        normalCode = rawCode - 0x10000;
                    else
                        normalCode = rawCode;

                    if (dataFormat == false)
                        celsius = normalCode / Math.Pow(2, 8);
                    else
                        celsius = normalCode / Math.Pow(2, 8) + 64;

                    if (unitCelsius == true)
                        return celsius;
                    else
                        return celsiusToFahrenheit(celsius);

                }*/

        //        short temperatureToHex(double temperature)
        //        {
        //            return (short)(temperature * Math.Pow(2, 8));
        //        }
        //
        //        double celsiusToFahrenheit(double temperature)
        //        {
        //            return temperature * 9 / 5 + 32;
        //        }

    }
}
