/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include "ExitAirTempSensor.hpp"

#include "Utils.hpp"
#include "VariantVisitors.hpp"

#include <boost/algorithm/string/replace.hpp>
#include <boost/container/flat_map.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/bus/match.hpp>

#include <array>
#include <chrono>
#include <cmath>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <numeric>
#include <stdexcept>
#include <utility>
#include <variant>
#include <vector>

constexpr const double altitudeFactor = 1.14;
constexpr const char* exitAirType = "ExitAirTempSensor";
constexpr const char* cfmType = "CFMSensor";

// todo: this *might* need to be configurable
constexpr const char* inletTemperatureSensor = "temperature/Front_Panel_Temp";
constexpr const char* pidConfigurationType =
    "xyz.openbmc_project.Configuration.Pid";
constexpr const char* settingsDaemon = "xyz.openbmc_project.Settings";
constexpr const char* cfmSettingPath = "/xyz/openbmc_project/control/cfm_limit";
constexpr const char* cfmSettingIface = "xyz.openbmc_project.Control.CFMLimit";

static constexpr bool debug = false;

static constexpr double cfmMaxReading = 255;
static constexpr double cfmMinReading = 0;

static constexpr size_t minSystemCfm = 50;

constexpr const auto monitorTypes{
    std::to_array<const char*>({exitAirType, cfmType})};

static std::vector<std::shared_ptr<CFMSensor>> cfmSensors;

static void setupSensorMatch(
    std::vector<sdbusplus::bus::match_t>& matches, sdbusplus::bus_t& connection,
    const std::string& type,
    std::function<void(const double&, sdbusplus::message_t&)>&& callback)
{
    std::function<void(sdbusplus::message_t & message)> eventHandler =
        [callback{std::move(callback)}](sdbusplus::message_t& message) {
        std::string objectName;
        boost::container::flat_map<std::string, std::variant<double, int64_t>>
            values;
        message.read(objectName, values);
        auto findValue = values.find("Value");
        if (findValue == values.end())
        {
            return;
        }
        double value = std::visit(VariantToDoubleVisitor(), findValue->second);
        if (std::isnan(value))
        {
            return;
        }

        callback(value, message);
    };
    matches.emplace_back(connection,
                         "type='signal',"
                         "member='PropertiesChanged',interface='org."
                         "freedesktop.DBus.Properties',path_"
                         "namespace='/xyz/openbmc_project/sensors/" +
                             std::string(type) +
                             "',arg0='xyz.openbmc_project.Sensor.Value'",
                         std::move(eventHandler));
}

static void setMaxPWM(const std::shared_ptr<sdbusplus::asio::connection>& conn,
                      double value)
{
    using GetSubTreeType = std::vector<std::pair<
        std::string,
        std::vector<std::pair<std::string, std::vector<std::string>>>>>;

    conn->async_method_call(
        [conn, value](const boost::system::error_code ec,
                      const GetSubTreeType& ret) {
        if (ec)
        {
            std::cerr << "Error calling mapper\n";
            return;
        }
        for (const auto& [path, objDict] : ret)
        {
            if (objDict.empty())
            {
                return;
            }
            const std::string& owner = objDict.begin()->first;

            conn->async_method_call(
                [conn, value, owner,
                 path{path}](const boost::system::error_code ec,
                             const std::variant<std::string>& classType) {
                if (ec)
                {
                    std::cerr << "Error getting pid class\n";
                    return;
                }
                const auto* classStr = std::get_if<std::string>(&classType);
                if (classStr == nullptr || *classStr != "fan")
                {
                    return;
                }
                conn->async_method_call(
                    [](boost::system::error_code& ec) {
                    if (ec)
                    {
                        std::cerr << "Error setting pid class\n";
                        return;
                    }
                },
                    owner, path, "org.freedesktop.DBus.Properties", "Set",
                    pidConfigurationType, "OutLimitMax",
                    std::variant<double>(value));
            },
                owner, path, "org.freedesktop.DBus.Properties", "Get",
                pidConfigurationType, "Class");
        }
    },
        mapper::busName, mapper::path, mapper::interface, mapper::subtree, "/",
        0, std::array<std::string, 1>{pidConfigurationType});
}

CFMSensor::CFMSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
                     const std::string& sensorName,
                     const std::string& sensorConfiguration,
                     sdbusplus::asio::object_server& objectServer,
                     std::vector<thresholds::Threshold>&& thresholdData,
                     std::shared_ptr<ExitAirTempSensor>& parent) :
    Sensor(escapeName(sensorName), std::move(thresholdData),
           sensorConfiguration, "CFMSensor", false, false, cfmMaxReading,
           cfmMinReading, conn, PowerState::on),
    parent(parent), objServer(objectServer)
{
    sensorInterface = objectServer.add_interface(
        "/xyz/openbmc_project/sensors/airflow/" + name,
        "xyz.openbmc_project.Sensor.Value");

    for (const auto& threshold : thresholds)
    {
        std::string interface = thresholds::getInterface(threshold.level);
        thresholdInterfaces[static_cast<size_t>(threshold.level)] =
            objectServer.add_interface(
                "/xyz/openbmc_project/sensors/airflow/" + name, interface);
    }

    association = objectServer.add_interface(
        "/xyz/openbmc_project/sensors/airflow/" + name, association::interface);

    setInitialProperties(sensor_paths::unitCFM);

    pwmLimitIface =
        objectServer.add_interface("/xyz/openbmc_project/control/pwm_limit",
                                   "xyz.openbmc_project.Control.PWMLimit");
    cfmLimitIface =
        objectServer.add_interface("/xyz/openbmc_project/control/MaxCFM",
                                   "xyz.openbmc_project.Control.CFMLimit");
}

void CFMSensor::setupMatches()
{
    std::weak_ptr<CFMSensor> weakRef = weak_from_this();
    setupSensorMatch(
        matches, *dbusConnection, "fan_tach",
        [weakRef](const double& value, sdbusplus::message_t& message) {
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }
        self->tachReadings[message.get_path()] = value;
        if (self->tachRanges.find(message.get_path()) == self->tachRanges.end())
        {
            // calls update reading after updating ranges
            self->addTachRanges(message.get_sender(), message.get_path());
        }
        else
        {
            self->updateReading();
        }
    });

    dbusConnection->async_method_call(
        [weakRef](const boost::system::error_code ec,
                  const std::variant<double> cfmVariant) {
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }

        uint64_t maxRpm = 100;
        if (!ec)
        {
            const auto* cfm = std::get_if<double>(&cfmVariant);
            if (cfm != nullptr && *cfm >= minSystemCfm)
            {
                maxRpm = self->getMaxRpm(*cfm);
            }
        }
        self->pwmLimitIface->register_property("Limit", maxRpm);
        self->pwmLimitIface->initialize();
        setMaxPWM(self->dbusConnection, maxRpm);
    },
        settingsDaemon, cfmSettingPath, "org.freedesktop.DBus.Properties",
        "Get", cfmSettingIface, "Limit");

    matches.emplace_back(*dbusConnection,
                         "type='signal',"
                         "member='PropertiesChanged',interface='org."
                         "freedesktop.DBus.Properties',path='" +
                             std::string(cfmSettingPath) + "',arg0='" +
                             std::string(cfmSettingIface) + "'",
                         [weakRef](sdbusplus::message_t& message) {
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }
        boost::container::flat_map<std::string, std::variant<double>> values;
        std::string objectName;
        message.read(objectName, values);
        const auto findValue = values.find("Limit");
        if (findValue == values.end())
        {
            return;
        }
        auto* const reading = std::get_if<double>(&(findValue->second));
        if (reading == nullptr)
        {
            std::cerr << "Got CFM Limit of wrong type\n";
            return;
        }
        if (*reading < minSystemCfm && *reading != 0)
        {
            std::cerr << "Illegal CFM setting detected\n";
            return;
        }
        uint64_t maxRpm = self->getMaxRpm(*reading);
        self->pwmLimitIface->set_property("Limit", maxRpm);
        setMaxPWM(self->dbusConnection, maxRpm);
    });
}

CFMSensor::~CFMSensor()
{
    for (const auto& iface : thresholdInterfaces)
    {
        objServer.remove_interface(iface);
    }
    objServer.remove_interface(sensorInterface);
    objServer.remove_interface(association);
    objServer.remove_interface(cfmLimitIface);
    objServer.remove_interface(pwmLimitIface);
}

void CFMSensor::createMaxCFMIface(void)
{
    cfmLimitIface->register_property("Limit", c2 * maxCFM * tachs.size());
    cfmLimitIface->initialize();
}

void CFMSensor::addTachRanges(const std::string& serviceName,
                              const std::string& path)
{
    std::weak_ptr<CFMSensor> weakRef = weak_from_this();
    dbusConnection->async_method_call(
        [weakRef, path](const boost::system::error_code ec,
                        const SensorBaseConfigMap& data) {
        if (ec)
        {
            std::cerr << "Error getting properties from " << path << "\n";
            return;
        }
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }
        double max = loadVariant<double>(data, "MaxValue");
        double min = loadVariant<double>(data, "MinValue");
        self->tachRanges[path] = std::make_pair(min, max);
        self->updateReading();
    },
        serviceName, path, "org.freedesktop.DBus.Properties", "GetAll",
        "xyz.openbmc_project.Sensor.Value");
}

void CFMSensor::checkThresholds(void)
{
    thresholds::checkThresholds(this);
}

void CFMSensor::updateReading(void)
{
    double val = 0.0;
    if (calculate(val))
    {
        if (value != val && parent)
        {
            parent->updateReading();
        }
        updateValue(val);
    }
    else
    {
        updateValue(std::numeric_limits<double>::quiet_NaN());
    }
}

uint64_t CFMSensor::getMaxRpm(uint64_t cfmMaxSetting) const
{
    uint64_t pwmPercent = 100;
    double totalCFM = std::numeric_limits<double>::max();
    if (cfmMaxSetting == 0)
    {
        return pwmPercent;
    }

    bool firstLoop = true;
    while (totalCFM > cfmMaxSetting)
    {
        if (firstLoop)
        {
            firstLoop = false;
        }
        else
        {
            pwmPercent--;
        }

        double ci = 0;
        if (pwmPercent == 0)
        {
            ci = 0;
        }
        else if (pwmPercent < tachMinPercent)
        {
            ci = c1;
        }
        else if (pwmPercent > tachMaxPercent)
        {
            ci = c2;
        }
        else
        {
            ci = c1 + (((c2 - c1) * (pwmPercent - tachMinPercent)) /
                       (tachMaxPercent - tachMinPercent));
        }

        // Now calculate the CFM for this tach
        // CFMi = Ci * Qmaxi * TACHi
        totalCFM = ci * maxCFM * pwmPercent;
        totalCFM *= tachs.size();
        // divide by 100 since pwm is in percent
        totalCFM /= 100;

        if (pwmPercent <= 0)
        {
            break;
        }
    }

    return pwmPercent;
}

bool CFMSensor::calculate(double& value)
{
    double totalCFM = 0;
    for (const std::string& tachName : tachs)
    {
        auto findReading = std::find_if(
            tachReadings.begin(), tachReadings.end(),
            [&](const auto& item) { return item.first.ends_with(tachName); });
        auto findRange = std::find_if(
            tachRanges.begin(), tachRanges.end(),
            [&](const auto& item) { return item.first.ends_with(tachName); });
        if (findReading == tachReadings.end())
        {
            if constexpr (debug)
            {
                std::cerr << "Can't find " << tachName << "in readings\n";
            }
            continue; // haven't gotten a reading
        }

        if (findRange == tachRanges.end())
        {
            std::cerr << "Can't find " << tachName << " in ranges\n";
            return false; // haven't gotten a max / min
        }

        // avoid divide by 0
        if (findRange->second.second == 0)
        {
            std::cerr << "Tach Max Set to 0 " << tachName << "\n";
            return false;
        }

        double rpm = findReading->second;

        // for now assume the min for a fan is always 0, divide by max to get
        // percent and mult by 100
        rpm /= findRange->second.second;
        rpm *= 100;

        if constexpr (debug)
        {
            std::cout << "Tach " << tachName << "at " << rpm << "\n";
        }

        // Do a linear interpolation to get Ci
        // Ci = C1 + (C2 - C1)/(RPM2 - RPM1) * (TACHi - TACH1)

        double ci = 0;
        if (rpm == 0)
        {
            ci = 0;
        }
        else if (rpm < tachMinPercent)
        {
            ci = c1;
        }
        else if (rpm > tachMaxPercent)
        {
            ci = c2;
        }
        else
        {
            ci = c1 + (((c2 - c1) * (rpm - tachMinPercent)) /
                       (tachMaxPercent - tachMinPercent));
        }

        // Now calculate the CFM for this tach
        // CFMi = Ci * Qmaxi * TACHi
        totalCFM += ci * maxCFM * rpm;
        if constexpr (debug)
        {
            std::cerr << "totalCFM = " << totalCFM << "\n";
            std::cerr << "Ci " << ci << " MaxCFM " << maxCFM << " rpm " << rpm
                      << "\n";
            std::cerr << "c1 " << c1 << " c2 " << c2 << " max "
                      << tachMaxPercent << " min " << tachMinPercent << "\n";
        }
    }

    // divide by 100 since rpm is in percent
    value = totalCFM / 100;
    if constexpr (debug)
    {
        std::cerr << "cfm value = " << value << "\n";
    }
    return true;
}

static constexpr double exitAirMaxReading = 127;
static constexpr double exitAirMinReading = -128;
ExitAirTempSensor::ExitAirTempSensor(
    std::shared_ptr<sdbusplus::asio::connection>& conn,
    const std::string& sensorName, const std::string& sensorConfiguration,
    sdbusplus::asio::object_server& objectServer,
    std::vector<thresholds::Threshold>&& thresholdData) :
    Sensor(escapeName(sensorName), std::move(thresholdData),
           sensorConfiguration, "ExitAirTemp", false, false, exitAirMaxReading,
           exitAirMinReading, conn, PowerState::on),
    objServer(objectServer)
{
    sensorInterface = objectServer.add_interface(
        "/xyz/openbmc_project/sensors/temperature/" + name,
        "xyz.openbmc_project.Sensor.Value");

    for (const auto& threshold : thresholds)
    {
        std::string interface = thresholds::getInterface(threshold.level);
        thresholdInterfaces[static_cast<size_t>(threshold.level)] =
            objectServer.add_interface(
                "/xyz/openbmc_project/sensors/temperature/" + name, interface);
    }
    association = objectServer.add_interface(
        "/xyz/openbmc_project/sensors/temperature/" + name,
        association::interface);
    setInitialProperties(sensor_paths::unitDegreesC);
}

ExitAirTempSensor::~ExitAirTempSensor()
{
    for (const auto& iface : thresholdInterfaces)
    {
        objServer.remove_interface(iface);
    }
    objServer.remove_interface(sensorInterface);
    objServer.remove_interface(association);
}

void ExitAirTempSensor::setupMatches(void)
{
    constexpr const auto matchTypes{
        std::to_array<const char*>({"power", inletTemperatureSensor})};

    std::weak_ptr<ExitAirTempSensor> weakRef = weak_from_this();
    for (const std::string type : matchTypes)
    {
        setupSensorMatch(matches, *dbusConnection, type,
                         [weakRef, type](const double& value,
                                         sdbusplus::message_t& message) {
            auto self = weakRef.lock();
            if (!self)
            {
                return;
            }
            if (type == "power")
            {
                std::string path = message.get_path();
                if (path.find("PS") != std::string::npos &&
                    path.ends_with("Input_Power"))
                {
                    self->powerReadings[message.get_path()] = value;
                }
            }
            else if (type == inletTemperatureSensor)
            {
                self->inletTemp = value;
            }
            self->updateReading();
        });
    }
    dbusConnection->async_method_call(
        [weakRef](boost::system::error_code ec,
                  const std::variant<double>& value) {
        if (ec)
        {
            // sensor not ready yet
            return;
        }
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }
        self->inletTemp = std::visit(VariantToDoubleVisitor(), value);
    },
        "xyz.openbmc_project.HwmonTempSensor",
        std::string("/xyz/openbmc_project/sensors/") + inletTemperatureSensor,
        properties::interface, properties::get, sensorValueInterface, "Value");
    dbusConnection->async_method_call(
        [weakRef](boost::system::error_code ec, const GetSubTreeType& subtree) {
        if (ec)
        {
            std::cerr << "Error contacting mapper\n";
            return;
        }
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }
        for (const auto& [path, matches] : subtree)
        {
            size_t lastSlash = path.rfind('/');
            if (lastSlash == std::string::npos || lastSlash == path.size() ||
                matches.empty())
            {
                continue;
            }
            std::string sensorName = path.substr(lastSlash + 1);
            if (sensorName.starts_with("PS") &&
                sensorName.ends_with("Input_Power"))
            {
                // lambda capture requires a proper variable (not a structured
                // binding)
                const std::string& cbPath = path;
                self->dbusConnection->async_method_call(
                    [weakRef, cbPath](boost::system::error_code ec,
                                      const std::variant<double>& value) {
                    if (ec)
                    {
                        std::cerr << "Error getting value from " << cbPath
                                  << "\n";
                    }
                    auto self = weakRef.lock();
                    if (!self)
                    {
                        return;
                    }
                    double reading = std::visit(VariantToDoubleVisitor(),
                                                value);
                    if constexpr (debug)
                    {
                        std::cerr << cbPath << "Reading " << reading << "\n";
                    }
                    self->powerReadings[cbPath] = reading;
                },
                    matches[0].first, cbPath, properties::interface,
                    properties::get, sensorValueInterface, "Value");
            }
        }
    },
        mapper::busName, mapper::path, mapper::interface, mapper::subtree,
        "/xyz/openbmc_project/sensors/power", 0,
        std::array<const char*, 1>{sensorValueInterface});
}

void ExitAirTempSensor::updateReading(void)
{
    double val = 0.0;
    if (calculate(val))
    {
        val = std::floor(val + 0.5);
        updateValue(val);
    }
    else
    {
        updateValue(std::numeric_limits<double>::quiet_NaN());
    }
}

double ExitAirTempSensor::getTotalCFM(void)
{
    double sum = 0;
    for (auto& sensor : cfmSensors)
    {
        double reading = 0;
        if (!sensor->calculate(reading))
        {
            return -1;
        }
        sum += reading;
    }

    return sum;
}

bool ExitAirTempSensor::calculate(double& val)
{
    constexpr size_t maxErrorPrint = 5;
    static bool firstRead = false;
    static size_t errorPrint = maxErrorPrint;

    double cfm = getTotalCFM();
    if (cfm <= 0)
    {
        std::cerr << "Error getting cfm\n";
        return false;
    }

    // Though cfm is not expected to be less than qMin normally,
    // it is not a hard limit for exit air temp calculation.
    // 50% qMin is chosen as a generic limit between providing
    // a valid derived exit air temp and reporting exit air temp not available.
    constexpr const double cfmLimitFactor = 0.5;
    if (cfm < (qMin * cfmLimitFactor))
    {
        if (errorPrint > 0)
        {
            errorPrint--;
            std::cerr << "cfm " << cfm << " is too low, expected qMin " << qMin
                      << "\n";
        }
        val = 0;
        return false;
    }

    // if there is an error getting inlet temp, return error
    if (std::isnan(inletTemp))
    {
        if (errorPrint > 0)
        {
            errorPrint--;
            std::cerr << "Cannot get inlet temp\n";
        }
        val = 0;
        return false;
    }

    // if fans are off, just make the exit temp equal to inlet
    if (!isPowerOn())
    {
        val = inletTemp;
        return true;
    }

    double totalPower = 0;
    for (const auto& [path, reading] : powerReadings)
    {
        if (std::isnan(reading))
        {
            continue;
        }
        totalPower += reading;
    }

    // Calculate power correction factor
    // Ci = CL + (CH - CL)/(QMax - QMin) * (CFM - QMin)
    double powerFactor = 0.0;
    if (cfm <= qMin)
    {
        powerFactor = powerFactorMin;
    }
    else if (cfm >= qMax)
    {
        powerFactor = powerFactorMax;
    }
    else
    {
        powerFactor = powerFactorMin + ((powerFactorMax - powerFactorMin) /
                                        (qMax - qMin) * (cfm - qMin));
    }

    totalPower *= powerFactor;
    totalPower += pOffset;

    if (totalPower == 0)
    {
        if (errorPrint > 0)
        {
            errorPrint--;
            std::cerr << "total power 0\n";
        }
        val = 0;
        return false;
    }

    if constexpr (debug)
    {
        std::cout << "Power Factor " << powerFactor << "\n";
        std::cout << "Inlet Temp " << inletTemp << "\n";
        std::cout << "Total Power" << totalPower << "\n";
    }

    // Calculate the exit air temp
    // Texit = Tfp + (1.76 * TotalPower / CFM * Faltitude)
    double reading = 1.76 * totalPower * altitudeFactor;
    reading /= cfm;
    reading += inletTemp;

    if constexpr (debug)
    {
        std::cout << "Reading 1: " << reading << "\n";
    }

    // Now perform the exponential average
    // Calculate alpha based on SDR values and CFM
    // Ai = As + (Af - As)/(QMax - QMin) * (CFM - QMin)

    double alpha = 0.0;
    if (cfm < qMin)
    {
        alpha = alphaS;
    }
    else if (cfm >= qMax)
    {
        alpha = alphaF;
    }
    else
    {
        alpha = alphaS + ((alphaF - alphaS) * (cfm - qMin) / (qMax - qMin));
    }

    auto time = std::chrono::steady_clock::now();
    if (!firstRead)
    {
        firstRead = true;
        lastTime = time;
        lastReading = reading;
    }
    double alphaDT =
        std::chrono::duration_cast<std::chrono::seconds>(time - lastTime)
            .count() *
        alpha;

    // cap at 1.0 or the below fails
    if (alphaDT > 1.0)
    {
        alphaDT = 1.0;
    }

    if constexpr (debug)
    {
        std::cout << "AlphaDT: " << alphaDT << "\n";
    }

    reading = ((reading * alphaDT) + (lastReading * (1.0 - alphaDT)));

    if constexpr (debug)
    {
        std::cout << "Reading 2: " << reading << "\n";
    }

    val = reading;
    lastReading = reading;
    lastTime = time;
    errorPrint = maxErrorPrint;
    return true;
}

void ExitAirTempSensor::checkThresholds(void)
{
    thresholds::checkThresholds(this);
}

static void loadVariantPathArray(const SensorBaseConfigMap& data,
                                 const std::string& key,
                                 std::vector<std::string>& resp)
{
    auto it = data.find(key);
    if (it == data.end())
    {
        std::cerr << "Configuration missing " << key << "\n";
        throw std::invalid_argument("Key Missing");
    }
    BasicVariantType copy = it->second;
    std::vector<std::string> config = std::get<std::vector<std::string>>(copy);
    for (auto& str : config)
    {
        boost::replace_all(str, " ", "_");
    }
    resp = std::move(config);
}

void createSensor(sdbusplus::asio::object_server& objectServer,
                  std::shared_ptr<ExitAirTempSensor>& exitAirSensor,
                  std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
{
    if (!dbusConnection)
    {
        std::cerr << "Connection not created\n";
        return;
    }
    auto getter = std::make_shared<GetSensorConfiguration>(
        dbusConnection, [&objectServer, &dbusConnection,
                         &exitAirSensor](const ManagedObjectType& resp) {
        cfmSensors.clear();
        for (const auto& [path, interfaces] : resp)
        {
            for (const auto& [intf, cfg] : interfaces)
            {
                if (intf == configInterfaceName(exitAirType))
                {
                    // thresholds should be under the same path
                    std::vector<thresholds::Threshold> sensorThresholds;
                    parseThresholdsFromConfig(interfaces, sensorThresholds);

                    std::string name = loadVariant<std::string>(cfg, "Name");
                    exitAirSensor = std::make_shared<ExitAirTempSensor>(
                        dbusConnection, name, path.str, objectServer,
                        std::move(sensorThresholds));
                    exitAirSensor->powerFactorMin =
                        loadVariant<double>(cfg, "PowerFactorMin");
                    exitAirSensor->powerFactorMax =
                        loadVariant<double>(cfg, "PowerFactorMax");
                    exitAirSensor->qMin = loadVariant<double>(cfg, "QMin");
                    exitAirSensor->qMax = loadVariant<double>(cfg, "QMax");
                    exitAirSensor->alphaS = loadVariant<double>(cfg, "AlphaS");
                    exitAirSensor->alphaF = loadVariant<double>(cfg, "AlphaF");
                }
                else if (intf == configInterfaceName(cfmType))
                {
                    // thresholds should be under the same path
                    std::vector<thresholds::Threshold> sensorThresholds;
                    parseThresholdsFromConfig(interfaces, sensorThresholds);
                    std::string name = loadVariant<std::string>(cfg, "Name");
                    auto sensor = std::make_shared<CFMSensor>(
                        dbusConnection, name, path.str, objectServer,
                        std::move(sensorThresholds), exitAirSensor);
                    loadVariantPathArray(cfg, "Tachs", sensor->tachs);
                    sensor->maxCFM = loadVariant<double>(cfg, "MaxCFM");

                    // change these into percent upon getting the data
                    sensor->c1 = loadVariant<double>(cfg, "C1") / 100;
                    sensor->c2 = loadVariant<double>(cfg, "C2") / 100;
                    sensor->tachMinPercent =
                        loadVariant<double>(cfg, "TachMinPercent");
                    sensor->tachMaxPercent =
                        loadVariant<double>(cfg, "TachMaxPercent");
                    sensor->createMaxCFMIface();
                    sensor->setupMatches();

                    cfmSensors.emplace_back(std::move(sensor));
                }
            }
        }
        if (exitAirSensor)
        {
            exitAirSensor->setupMatches();
            exitAirSensor->updateReading();
        }
    });
    getter->getConfiguration(
        std::vector<std::string>(monitorTypes.begin(), monitorTypes.end()));
}

int main()
{
    boost::asio::io_context io;
    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
    sdbusplus::asio::object_server objectServer(systemBus, true);
    objectServer.add_manager("/xyz/openbmc_project/sensors");
    systemBus->request_name("xyz.openbmc_project.ExitAirTempSensor");
    std::shared_ptr<ExitAirTempSensor> sensor =
        nullptr; // wait until we find the config

    boost::asio::post(io,
                      [&]() { createSensor(objectServer, sensor, systemBus); });

    boost::asio::steady_timer configTimer(io);

    std::function<void(sdbusplus::message_t&)> eventHandler =
        [&](sdbusplus::message_t&) {
        configTimer.expires_after(std::chrono::seconds(1));
        // create a timer because normally multiple properties change
        configTimer.async_wait([&](const boost::system::error_code& ec) {
            if (ec == boost::asio::error::operation_aborted)
            {
                return; // we're being canceled
            }
            createSensor(objectServer, sensor, systemBus);
            if (!sensor)
            {
                std::cout << "Configuration not detected\n";
            }
        });
    };
    std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
        setupPropertiesChangedMatches(*systemBus, monitorTypes, eventHandler);

    setupManufacturingModeMatch(*systemBus);
    io.run();
    return 0;
}
