// bytran -|- spectral calculations for portable devices using the HITRAN database
//
// Developed by Dzianis Pliutau (Denis Plutov) and Kostya Roslyakov
// www.bytran.org | contact@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 transfer over data from the sensors C++ class to/from the QML interface
#include "sensorsdataobject.h"

SensorsDataObject::SensorsDataObject(QObject *parent, BytranCore *inCore) : QObject(parent)
{
    // Transferring a reference to the core object to the sensors data object
    core = inCore;

    // So that commas are not inserted into numbers
    loc.setNumberOptions(QLocale::OmitGroupSeparator);

    // Getting the enabled states for sensors
    m_totalPressureSensorEnabled = core->getSensors()->getTotalPressureSensorIsEnabled();
    m_temperatureSensorEnabled = core->getSensors()->getTemperatureSensorIsEnabled();
    m_humiditySensorEnabled = core->getSensors()->getHumiditySensorIsEnabled();

    // Connecting a sensor update signal
    connect(this->core->getSensors(), SIGNAL(totalPressureUpdated()), this, SLOT(updateTotalPressureValue()));
    connect(this->core->getSensors(), SIGNAL(temperatureUpdated()), this, SLOT(updateTemperatureValue()));
    connect(this->core->getSensors(), SIGNAL(humidityUpdated()), this, SLOT(updateHumidityValue()));
    connect(this->core->getSensors(), SIGNAL(barometerActiveChanged()), this, SLOT(updateBarometerActiveState()));
    connect(this->core->getSensors(), SIGNAL(thermometerActiveChanged()), this, SLOT(updateThermometerActiveState()));
    connect(this->core->getSensors(), SIGNAL(humiditySensorActiveChanged()), this, SLOT(updateHumiditySensorActiveState()));
}

QString SensorsDataObject::totalPressure() const
{
    double totalPressAtm;        // Total pressure in default internal units (atm)
    double totalPressCurrUnits;  // Total pressure in current pressure units

    totalPressAtm = core->getParams()->getHorizParams()->getTotalPress();
    totalPressCurrUnits = core->getConcPressUnitsConverter()->fromDefaultToCurrentPressUnits(totalPressAtm);
    return loc.toString(totalPressCurrUnits, 'g', 6) + " (" + core->getConcPressUnitsConverter()->getCurrPressUnitsAbbrevStr() + ")";
}
QString SensorsDataObject::temperature() const
{
    double tempK;          // Temperature in Kelvin units
    double tempCurrUnits;  // Temperature in current units

    tempK = core->getParams()->getHorizParams()->getTemp();
    tempCurrUnits = core->getTemperatureUnitsConverter()->fromDefaultToCurrent(tempK);
    return loc.toString(tempCurrUnits, 'g', 6) + " (" + core->getTemperatureUnitsConverter()->getCurrTempUnitsAbbrevStr() + ")";
}
QString SensorsDataObject::humidity() const
{
    QString concStr = "0";
    double h2oPpmv;  // H2O concentration in PPMV
    double conc;  // Concentration value, %


    // Updating the concentration values to be displayed
    h2oPpmv = core->getParams()->getHorizParams()->getPartPress(0);
    conc = core->getConcPressUnitsConverter()->fromDefaultToCurrentConcUnits(h2oPpmv, core->getParams()->getHorizParams()->getTotalPress());
    concStr = loc.toString(conc, 'g', 5);

    return concStr + " (" + core->getConcPressUnitsConverter()->getCurrCombinedUnitsAbbrevStr() + ")";
}

int SensorsDataObject::samplingPeriod() const { return core->getSensors()->getSamplingPeriod(); }
void SensorsDataObject::setSamplingPeriod(int const samplingPeriod)
{
    if (samplingPeriod != this->m_samplingPeriod)
    {
        m_samplingPeriod = samplingPeriod;
        core->getSensors()->setSampligPeriod(m_samplingPeriod);
        emit samplingPeriodChanged();
        emit averagingTimeChanged();
    }
}
int SensorsDataObject::numSamplesToAverage() const { return core->getSensors()->getNumSamplesToAverage(); }
void SensorsDataObject::setNumSamplesToAverage(int const numSamplesToAverage)
{
    if (numSamplesToAverage != this->m_numSamplesToAverage)
    {
        m_numSamplesToAverage = numSamplesToAverage;
        core->getSensors()->setNumSamplesToAverage(m_numSamplesToAverage);
        emit numSamplesToAverageChanged();
        emit averagingTimeChanged();
    }
}
int SensorsDataObject::averagingTime() const
{
    int avgTime;
    avgTime = this->m_samplingPeriod * this->m_numSamplesToAverage;
    return avgTime;
}

bool SensorsDataObject::totalPressureSensorEnabled() const { return core->getSensors()->getTotalPressureSensorIsEnabled(); }
void SensorsDataObject::setTotalPressureSensorEnabled(const bool totalPressureSensorEnabled)
{
    if (totalPressureSensorEnabled != m_totalPressureSensorEnabled)
    {
        m_totalPressureSensorEnabled = totalPressureSensorEnabled;
        core->getSensors()->setEnableTotalPressureSensor(m_totalPressureSensorEnabled);
        emit totalPressureSensorEnabledChanged();
    }
}
bool SensorsDataObject::temperatureSensorEnabled() const { return core->getSensors()->getTemperatureSensorIsEnabled(); }
void SensorsDataObject::setTemperatureSensorEnabled(const bool temperatureSensorEnabled)
{
    if (temperatureSensorEnabled != m_temperatureSensorEnabled)
    {
        m_temperatureSensorEnabled = temperatureSensorEnabled;
        core->getSensors()->setEnableTemperatureSensor(m_temperatureSensorEnabled);
        emit temperatureSensorEnabledChanged();
    }
}
bool SensorsDataObject::humiditySensorEnabled() const { return core->getSensors()->getHumiditySensorIsEnabled(); }
void SensorsDataObject::setHumiditySensorEnabled(const bool humiditySensorEnabled)
{
    if (humiditySensorEnabled != m_humiditySensorEnabled)
    {
        m_humiditySensorEnabled = humiditySensorEnabled;
        core->getSensors()->setEnableHumiditySensor(m_humiditySensorEnabled);
        emit humiditySensorEnabledChanged();
    }
}

// Private slot to update the sensor values
void SensorsDataObject::updateTotalPressureValue() { emit totalPressureChanged(); }
void SensorsDataObject::updateTemperatureValue() { emit temperatureChanged(); }
void SensorsDataObject::updateHumidityValue() { emit humidityChanged(); }

// Private slots to update the sensor active states
void SensorsDataObject::updateBarometerActiveState() { emit totalPressureSensorEnabledChanged(); }
void SensorsDataObject::updateThermometerActiveState() { emit temperatureSensorEnabledChanged(); }
void SensorsDataObject::updateHumiditySensorActiveState() { emit humiditySensorEnabledChanged(); }

// Methods to establish if one of the below sensors is present
bool SensorsDataObject::totalPressureSensorIsPresent() { return core->getSensors()->getTotalPressureSensorIsPresent(); }
bool SensorsDataObject::temperatureSensorIsPresent() { return core->getSensors()->getTemperatureSensorIsPresent(); }
bool SensorsDataObject::humiditySensorIsPresent() { return core->getSensors()->getHumiditySensorIsPresent(); }

// Method shows if the humidity sensor is supported (Qt has to be version 5.9 or higher)
bool SensorsDataObject::humiditySensorIsSupported() { return core->getSensors()->getHumiditySensorIsSupported(); }
