// bytran -|- spectral calculations for portable devices using the HITRAN database
//
// Developed by Dzianis Pliutau (Denis Plutov) and Kostya Roslyakov
// www.bytran.org | bytran@bytran.org
// Copyright (c) 2016 Dzianis Pliutau
// Distributed under the MIT license
//
// The bytran logo is distributed under the Creative Commons 3.0 Attribution License: https://creativecommons.org/licenses/by/3.0/us/
//
// The MIT License (MIT)
// Copyright (c) 2016 Dzianis Pliutau
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// 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 THE AUTHORS OR COPYRIGHT HOLDERS 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.



// Object to retrieve values from sensors (pressure, temperature, humidity)
#ifndef SENSORS_H
#define SENSORS_H

// Qt humidity sensor is not available for Qt lower than 5.9, which is why a preprocessor directive has been introduced
// http://stackoverflow.com/questions/24899558/how-to-check-qt-version-to-include-different-header

#include <QObject>
#include <QTimer>
#include <QtSensors/QPressureSensor>
#include <QtSensors/QAmbientTemperatureSensor>
#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(5,9,0)  // The humidity sensor was introduced in Qt 5.9
    #include <QtSensors/QHumiditySensor>
#endif
#include <oneslantlayer.h>
#include "concpressunitsconvert.h"
#include "temperatureunitsconvert.h"
#include "humidityconvert.h"
#include "sensortag.h"
#include "sensorscellphone.h"
#include "sensehat.h"

class Sensors : public QObject
{
    Q_OBJECT
public:
    explicit Sensors(QObject *parent = 0, OneSlantLayer *inHorizPathParams = 0);

    // Methods to get and set the sampling period
    int getSamplingPeriod();
    void setSampligPeriod(int mSec);

    // Methods to start and stop the timer (may be used to temporarily disable sample acquisition)
    void stopTimer();
    void startTimer();

    // Methods to get and set the averaging time
    int getNumSamplesToAverage();
    void setNumSamplesToAverage(int number);

    // Methods to start and end data recording from total pressure sensors
    void setEnableTotalPressureSensor(bool enable);
    bool getTotalPressureSensorIsEnabled();
    void setEnableTemperatureSensor(bool enable);
    bool getTemperatureSensorIsEnabled();
    void setEnableHumiditySensor(bool enable);
    bool getHumiditySensorIsEnabled();

    // Methods to get the last recorded values from sensors
    double getTotalPressureAtm();
    double getTemperatureK();
    double getHumidityPpmv();

    // Methods to determine if sensors are available
    bool getTotalPressureSensorIsPresent();  // Method is used to indicate if a pressure sensor is available
    bool getTemperatureSensorIsPresent();    // Method is used to indicate if a temperature sensor is available
    bool getHumiditySensorIsPresent();       // Method is used to indicate if a humidity sensor is available

    // Methods to get and set the saved total pressure, temperature and humidity values
    double getSavedTotalPressure();
    void setSavedTotalPressure(double newSavedTotalPressure);
    double getSavedTemperature();
    void setSavedTemperature(double newSavedTemperature);
    double getSavedHumidity();
    void setSavedHumidity(double newSavedHumidity);

    // Methods are used to handle the variable indicating if the SensorTag is to be used
    bool getUseSensorTag();
    void setUseSensorTag(bool useSensorTagNew);

    // Method to connect and disconnect a SensorTag device
    void connectSensorTagDevice();
    void disconnectSensorTagDevice();

    // Method to get a pointer to the SensorTag object
    SensorTag *getSensorTag();

    // Method to get a pointer to the Cell Phone Sensors object
    SensorsCellPhone *getSensorsCellPhone();

    // Method to get a reference to the Sense HAT class
    SenseHat *getSenseHat();

signals:

    // Signal is emitted when the sensor tag emabled state is changed
    void useSensorTagStateChanged();

    // Signal is emited when the sensors data is updated
    void totalPressureUpdated();
    void temperatureUpdated();
    void humidityUpdated();

    // Signal is emited when the activated state of one of the sensors is changed
    void barometerActiveChanged();
    void thermometerActiveChanged();
    void humiditySensorActiveChanged();
    void sensorActiveChanged();

public slots:

private slots:

     // Slot is called to get the updated readings from the active sensors
     void getUpdatedReadings();

private:

    // Timer to record data from sensors in set intervals
    QTimer *timer;

    // Values recorded from sensors
    double totalPressureAtm;  // Averaged total pressure in Atm
    double temperatureK;      // Averaged temperature in Kelvin
    double humidityPpmv;      // Averaged "humidity" in Ppmv (for H2O)

    // Values used to calculate averaged total pressure, temperature and humidity
    double summedTotalPressureAtm;
    double summedTemperatureK;
    double summedHumidityPpmv;

    // Values of total pressure, temperature and humidity saved before switching to the sensor mode
    double savedTotalPressureAtm;
    double savedTemperatureK;
    double savedHumidityPpmv;

    // Variables indicating if the total pressure, temperature and humidity sensors are enabled
    bool totalPressureSensorEnabled;
    bool temperatureSensorEnabled;
    bool humiditySensorEnabled;

    // Variable to store the horizontal path parameters
    OneSlantLayer *horizParams;

    // Variable indicating the averaging time for the sensor data
    int averagingTime;
    int numSamplesToAverage;
    int numSummedSamples;

    // Variable indicates if the SensorTag is to be used
    bool useSensorTag;

    // SensorTag object to get the readings from the SensorTag object
    SensorTag *sensorTag;
    // Object to acquire readings from built in sensors
    SensorsCellPhone *sensorsCellPhone;
    // Object to get the sensor input from the Sense HAT board
    SenseHat *senseHat;

    // Object used to convert pressure from the specified units to the default (atm)
    ConcPressUnitsConvert *pressConverter;
    // Object used to convert temperature from specified units to the default (Kelvin)
    TemperatureUnitsConvert *tempConverter;
    // Object to convert the humidity from the sensor units to the default units
    HumidityConvert *humidityConverter;

};

#endif // SENSORS_H
