/*
// 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 "dbusconfiguration.hpp"

#include "conf.hpp"
#include "dbushelper.hpp"
#include "dbusutil.hpp"
#include "ec/stepwise.hpp"
#include "util.hpp"

#include <systemd/sd-bus.h>

#include <boost/asio/error.hpp>
#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/message/native_types.hpp>

#include <algorithm>
#include <array>
#include <chrono>
#include <cstdint>
#include <format>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <stdexcept>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

namespace pid_control
{

constexpr const char* pidConfigurationInterface =
    "xyz.openbmc_project.Configuration.Pid";
constexpr const char* objectManagerInterface =
    "org.freedesktop.DBus.ObjectManager";
constexpr const char* pidZoneConfigurationInterface =
    "xyz.openbmc_project.Configuration.Pid.Zone";
constexpr const char* stepwiseConfigurationInterface =
    "xyz.openbmc_project.Configuration.Stepwise";
constexpr const char* thermalControlIface =
    "xyz.openbmc_project.Control.ThermalMode";
constexpr const char* sensorInterface = "xyz.openbmc_project.Sensor.Value";
constexpr const char* defaultPwmInterface =
    "xyz.openbmc_project.Control.FanPwm";

using Association = std::tuple<std::string, std::string, std::string>;
using Associations = std::vector<Association>;

namespace thresholds
{
constexpr const char* warningInterface =
    "xyz.openbmc_project.Sensor.Threshold.Warning";
constexpr const char* criticalInterface =
    "xyz.openbmc_project.Sensor.Threshold.Critical";
const std::array<const char*, 4> types = {"CriticalLow", "CriticalHigh",
                                          "WarningLow", "WarningHigh"};

} // namespace thresholds

namespace dbus_configuration
{
using SensorInterfaceType = std::pair<std::string, std::string>;

inline std::string getSensorNameFromPath(const std::string& dbusPath)
{
    return dbusPath.substr(dbusPath.find_last_of('/') + 1);
}

inline std::string sensorNameToDbusName(const std::string& sensorName)
{
    std::string retString = sensorName;
    std::replace(retString.begin(), retString.end(), ' ', '_');
    return retString;
}

std::vector<std::string> getSelectedProfiles(sdbusplus::bus_t& bus)
{
    std::vector<std::string> ret;
    auto mapper =
        bus.new_method_call("xyz.openbmc_project.ObjectMapper",
                            "/xyz/openbmc_project/object_mapper",
                            "xyz.openbmc_project.ObjectMapper", "GetSubTree");
    mapper.append("/", 0, std::array<const char*, 1>{thermalControlIface});
    std::unordered_map<
        std::string, std::unordered_map<std::string, std::vector<std::string>>>
        respData;

    try
    {
        auto resp = bus.call(mapper);
        resp.read(respData);
    }
    catch (const sdbusplus::exception_t&)
    {
        // can't do anything without mapper call data
        throw std::runtime_error("ObjectMapper Call Failure");
    }
    if (respData.empty())
    {
        // if the user has profiles but doesn't expose the interface to select
        // one, just go ahead without using profiles
        return ret;
    }

    // assumption is that we should only have a small handful of selected
    // profiles at a time (probably only 1), so calling each individually should
    // not incur a large cost
    for (const auto& objectPair : respData)
    {
        const std::string& path = objectPair.first;
        for (const auto& ownerPair : objectPair.second)
        {
            const std::string& busName = ownerPair.first;
            auto getProfile =
                bus.new_method_call(busName.c_str(), path.c_str(),
                                    "org.freedesktop.DBus.Properties", "Get");
            getProfile.append(thermalControlIface, "Current");
            std::variant<std::string> variantResp;
            try
            {
                auto resp = bus.call(getProfile);
                resp.read(variantResp);
            }
            catch (const sdbusplus::exception_t&)
            {
                throw std::runtime_error("Failure getting profile");
            }
            std::string mode = std::get<std::string>(variantResp);
            ret.emplace_back(std::move(mode));
        }
    }
    if constexpr (pid_control::conf::DEBUG)
    {
        std::cout << "Profiles selected: ";
        for (const auto& profile : ret)
        {
            std::cout << profile << " ";
        }
        std::cout << "\n";
    }
    return ret;
}

int eventHandler(sd_bus_message* m, void* context, sd_bus_error*)
{
    if (context == nullptr || m == nullptr)
    {
        throw std::runtime_error("Invalid match");
    }

    // we skip associations because the mapper populates these, not the sensors
    const std::array<const char*, 2> skipList = {
        "xyz.openbmc_project.Association",
        "xyz.openbmc_project.Association.Definitions"};

    sdbusplus::message_t message(m);
    if (std::string(message.get_member()) == "InterfacesAdded")
    {
        sdbusplus::message::object_path path;
        std::unordered_map<
            std::string,
            std::unordered_map<std::string, std::variant<Associations, bool>>>
            data;

        message.read(path, data);

        for (const char* skip : skipList)
        {
            auto find = data.find(skip);
            if (find != data.end())
            {
                data.erase(find);
                if (data.empty())
                {
                    return 1;
                }
            }
        }

        if constexpr (pid_control::conf::DEBUG)
        {
            std::cout << "New config detected: " << path.str << std::endl;
            for (auto& d : data)
            {
                std::cout << "\tdata is " << d.first << std::endl;
                for (auto& second : d.second)
                {
                    std::cout << "\t\tdata is " << second.first << std::endl;
                }
            }
        }
    }

    boost::asio::steady_timer* timer =
        static_cast<boost::asio::steady_timer*>(context);

    // do a brief sleep as we tend to get a bunch of these events at
    // once
    timer->expires_after(std::chrono::seconds(2));
    timer->async_wait([](const boost::system::error_code ec) {
        if (ec == boost::asio::error::operation_aborted)
        {
            /* another timer started*/
            return;
        }

        std::cout << "New configuration detected, reloading\n.";
        tryRestartControlLoops();
    });

    return 1;
}

void createMatches(sdbusplus::bus_t& bus, boost::asio::steady_timer& timer)
{
    // this is a list because the matches can't be moved
    static std::list<sdbusplus::bus::match_t> matches;

    const std::array<std::string, 4> interfaces = {
        thermalControlIface, pidConfigurationInterface,
        pidZoneConfigurationInterface, stepwiseConfigurationInterface};

    // this list only needs to be created once
    if (!matches.empty())
    {
        return;
    }

    // we restart when the configuration changes or there are new sensors
    for (const auto& interface : interfaces)
    {
        matches.emplace_back(
            bus,
            "type='signal',member='PropertiesChanged',arg0namespace='" +
                interface + "'",
            eventHandler, &timer);
    }
    matches.emplace_back(
        bus,
        "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
        "sensors/'",
        eventHandler, &timer);
    matches.emplace_back(bus,
                         "type='signal',member='InterfacesRemoved',arg0path='/"
                         "xyz/openbmc_project/sensors/'",
                         eventHandler, &timer);
}

/**
 * retrieve an attribute from the pid configuration map
 * @param[in] base - the PID configuration map, keys are the attributes and
 * value is the variant associated with that attribute.
 * @param attributeName - the name of the attribute
 * @return a variant holding the value associated with a key
 * @throw runtime_error : attributeName is not in base
 */
inline DbusVariantType getPIDAttribute(
    const std::unordered_map<std::string, DbusVariantType>& base,
    const std::string& attributeName)
{
    auto search = base.find(attributeName);
    if (search == base.end())
    {
        throw std::runtime_error("missing attribute " + attributeName);
    }
    return search->second;
}

inline void getCycleTimeSetting(
    const std::unordered_map<std::string, DbusVariantType>& zone,
    const int zoneIndex, const std::string& attributeName, uint64_t& value)
{
    auto findAttributeName = zone.find(attributeName);
    if (findAttributeName != zone.end())
    {
        double tmpAttributeValue =
            std::visit(VariantToDoubleVisitor(), zone.at(attributeName));
        if (tmpAttributeValue >= 1.0)
        {
            value = static_cast<uint64_t>(tmpAttributeValue);
        }
        else
        {
            std::cerr << "Zone " << zoneIndex << ": " << attributeName
                      << " is invalid. Use default " << value << " ms\n";
        }
    }
    else
    {
        std::cerr << "Zone " << zoneIndex << ": " << attributeName
                  << " cannot find setting. Use default " << value << " ms\n";
    }
}

void populatePidInfo(
    sdbusplus::bus_t& bus,
    const std::unordered_map<std::string, DbusVariantType>& base,
    conf::ControllerInfo& info, const std::string* thresholdProperty,
    const std::map<std::string, conf::SensorConfig>& sensorConfig)
{
    info.type = std::get<std::string>(getPIDAttribute(base, "Class"));
    if (info.type == "fan")
    {
        info.setpoint = 0;
    }
    else
    {
        info.setpoint = std::visit(VariantToDoubleVisitor(),
                                   getPIDAttribute(base, "SetPoint"));
    }

    int failsafepercent = 0;
    auto findFailSafe = base.find("FailSafePercent");
    if (findFailSafe != base.end())
    {
        failsafepercent = std::visit(VariantToDoubleVisitor(),
                                     getPIDAttribute(base, "FailSafePercent"));
    }
    info.failSafePercent = failsafepercent;

    if (thresholdProperty != nullptr)
    {
        std::string interface;
        if (*thresholdProperty == "WarningHigh" ||
            *thresholdProperty == "WarningLow")
        {
            interface = thresholds::warningInterface;
        }
        else
        {
            interface = thresholds::criticalInterface;
        }

        // Although this checks only the first vector element for the
        // named threshold, it is OK, because the SetPointOffset parser
        // splits up the input into individual vectors, each with only a
        // single element, if it detects that SetPointOffset is in use.
        const std::string& path =
            sensorConfig.at(info.inputs.front().name).readPath;

        DbusHelper helper(bus);
        std::string service = helper.getService(interface, path);
        double reading = 0;
        try
        {
            helper.getProperty(service, path, interface, *thresholdProperty,
                               reading);
        }
        catch (const sdbusplus::exception_t& ex)
        {
            // unsupported threshold, leaving reading at 0
        }

        info.setpoint += reading;
    }

    info.pidInfo.ts = 1.0; // currently unused
    info.pidInfo.proportionalCoeff = std::visit(
        VariantToDoubleVisitor(), getPIDAttribute(base, "PCoefficient"));
    info.pidInfo.integralCoeff = std::visit(
        VariantToDoubleVisitor(), getPIDAttribute(base, "ICoefficient"));
    // DCoefficient is below, it is optional, same reason as in buildjson.cpp
    info.pidInfo.feedFwdOffset = std::visit(
        VariantToDoubleVisitor(), getPIDAttribute(base, "FFOffCoefficient"));
    info.pidInfo.feedFwdGain = std::visit(
        VariantToDoubleVisitor(), getPIDAttribute(base, "FFGainCoefficient"));
    info.pidInfo.integralLimit.max = std::visit(
        VariantToDoubleVisitor(), getPIDAttribute(base, "ILimitMax"));
    info.pidInfo.integralLimit.min = std::visit(
        VariantToDoubleVisitor(), getPIDAttribute(base, "ILimitMin"));
    info.pidInfo.outLim.max = std::visit(VariantToDoubleVisitor(),
                                         getPIDAttribute(base, "OutLimitMax"));
    info.pidInfo.outLim.min = std::visit(VariantToDoubleVisitor(),
                                         getPIDAttribute(base, "OutLimitMin"));
    info.pidInfo.slewNeg =
        std::visit(VariantToDoubleVisitor(), getPIDAttribute(base, "SlewNeg"));
    info.pidInfo.slewPos =
        std::visit(VariantToDoubleVisitor(), getPIDAttribute(base, "SlewPos"));

    bool checkHysterWithSetpt = false;
    double negativeHysteresis = 0;
    double positiveHysteresis = 0;
    double derivativeCoeff = 0;

    auto findCheckHysterFlag = base.find("CheckHysteresisWithSetpoint");
    auto findNeg = base.find("NegativeHysteresis");
    auto findPos = base.find("PositiveHysteresis");
    auto findDerivative = base.find("DCoefficient");

    if (findCheckHysterFlag != base.end())
    {
        checkHysterWithSetpt = std::get<bool>(findCheckHysterFlag->second);
    }
    if (findNeg != base.end())
    {
        negativeHysteresis =
            std::visit(VariantToDoubleVisitor(), findNeg->second);
    }
    if (findPos != base.end())
    {
        positiveHysteresis =
            std::visit(VariantToDoubleVisitor(), findPos->second);
    }
    if (findDerivative != base.end())
    {
        derivativeCoeff =
            std::visit(VariantToDoubleVisitor(), findDerivative->second);
    }

    info.pidInfo.checkHysterWithSetpt = checkHysterWithSetpt;
    info.pidInfo.negativeHysteresis = negativeHysteresis;
    info.pidInfo.positiveHysteresis = positiveHysteresis;
    info.pidInfo.derivativeCoeff = derivativeCoeff;
}

bool init(sdbusplus::bus_t& bus, boost::asio::steady_timer& timer,
          std::map<std::string, conf::SensorConfig>& sensorConfig,
          std::map<int64_t, conf::PIDConf>& zoneConfig,
          std::map<int64_t, conf::ZoneConfig>& zoneDetailsConfig)
{
    sensorConfig.clear();
    zoneConfig.clear();
    zoneDetailsConfig.clear();

    createMatches(bus, timer);

    auto mapper =
        bus.new_method_call("xyz.openbmc_project.ObjectMapper",
                            "/xyz/openbmc_project/object_mapper",
                            "xyz.openbmc_project.ObjectMapper", "GetSubTree");
    mapper.append(
        "/", 0,
        std::array<const char*, 6>{
            objectManagerInterface, pidConfigurationInterface,
            pidZoneConfigurationInterface, stepwiseConfigurationInterface,
            sensorInterface, defaultPwmInterface});
    std::unordered_map<
        std::string, std::unordered_map<std::string, std::vector<std::string>>>
        respData;
    try
    {
        auto resp = bus.call(mapper);
        resp.read(respData);
    }
    catch (const sdbusplus::exception_t&)
    {
        // can't do anything without mapper call data
        throw std::runtime_error("ObjectMapper Call Failure");
    }

    if (respData.empty())
    {
        // can't do anything without mapper call data
        throw std::runtime_error("No configuration data available from Mapper");
    }
    // create a map of pair of <has pid configuration, ObjectManager path>
    std::unordered_map<std::string, std::pair<bool, std::string>> owners;
    // and a map of <path, interface> for sensors
    std::unordered_map<std::string, std::string> sensors;
    for (const auto& objectPair : respData)
    {
        for (const auto& ownerPair : objectPair.second)
        {
            auto& owner = owners[ownerPair.first];
            for (const std::string& interface : ownerPair.second)
            {
                if (interface == objectManagerInterface)
                {
                    owner.second = objectPair.first;
                }
                if (interface == pidConfigurationInterface ||
                    interface == pidZoneConfigurationInterface ||
                    interface == stepwiseConfigurationInterface)
                {
                    owner.first = true;
                }
                if (interface == sensorInterface ||
                    interface == defaultPwmInterface)
                {
                    // we're not interested in pwm sensors, just pwm control
                    if (interface == sensorInterface &&
                        objectPair.first.find("pwm") != std::string::npos)
                    {
                        continue;
                    }
                    sensors[objectPair.first] = interface;
                }
            }
        }
    }
    ManagedObjectType configurations;
    for (const auto& owner : owners)
    {
        // skip if no pid configuration (means probably a sensor)
        if (!owner.second.first)
        {
            continue;
        }
        auto endpoint = bus.new_method_call(
            owner.first.c_str(), owner.second.second.c_str(),
            "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
        ManagedObjectType configuration;
        try
        {
            auto response = bus.call(endpoint);
            response.read(configuration);
        }
        catch (const sdbusplus::exception_t&)
        {
            // this shouldn't happen, probably means daemon crashed
            throw std::runtime_error(
                "Error getting managed objects from " + owner.first);
        }

        for (auto& pathPair : configuration)
        {
            if (pathPair.second.find(pidConfigurationInterface) !=
                    pathPair.second.end() ||
                pathPair.second.find(pidZoneConfigurationInterface) !=
                    pathPair.second.end() ||
                pathPair.second.find(stepwiseConfigurationInterface) !=
                    pathPair.second.end())
            {
                configurations.emplace(pathPair);
            }
        }
    }

    // remove controllers from config that aren't in the current profile(s)
    std::vector<std::string> selectedProfiles = getSelectedProfiles(bus);
    if (selectedProfiles.size())
    {
        for (auto pathIt = configurations.begin();
             pathIt != configurations.end();)
        {
            for (auto confIt = pathIt->second.begin();
                 confIt != pathIt->second.end();)
            {
                auto profilesFind = confIt->second.find("Profiles");
                if (profilesFind == confIt->second.end())
                {
                    confIt++;
                    continue; // if no profiles selected, apply always
                }
                auto profiles =
                    std::get<std::vector<std::string>>(profilesFind->second);
                if (profiles.empty())
                {
                    confIt++;
                    continue;
                }

                bool found = false;
                for (const std::string& profile : profiles)
                {
                    if (std::find(selectedProfiles.begin(),
                                  selectedProfiles.end(), profile) !=
                        selectedProfiles.end())
                    {
                        found = true;
                        break;
                    }
                }
                if (found)
                {
                    confIt++;
                }
                else
                {
                    confIt = pathIt->second.erase(confIt);
                }
            }
            if (pathIt->second.empty())
            {
                pathIt = configurations.erase(pathIt);
            }
            else
            {
                pathIt++;
            }
        }
    }

    // On D-Bus, although not necessary,
    // having the "zoneID" field can still be useful,
    // as it is used for diagnostic messages,
    // logging file names, and so on.
    // Accept optional "ZoneIndex" parameter to explicitly specify.
    // If not present, or not unique, auto-assign index,
    // using 0-based numbering, ensuring uniqueness.
    std::map<std::string, int64_t> foundZones;
    for (const auto& configuration : configurations)
    {
        auto findZone =
            configuration.second.find(pidZoneConfigurationInterface);
        if (findZone != configuration.second.end())
        {
            const auto& zone = findZone->second;

            const std::string& name = std::get<std::string>(zone.at("Name"));

            auto findZoneIndex = zone.find("ZoneIndex");
            if (findZoneIndex == zone.end())
            {
                continue;
            }

            auto ptrZoneIndex = std::get_if<double>(&(findZoneIndex->second));
            if (!ptrZoneIndex)
            {
                continue;
            }

            auto desiredIndex = static_cast<int64_t>(*ptrZoneIndex);
            auto grantedIndex = setZoneIndex(name, foundZones, desiredIndex);
            std::cout << "Zone " << name << " is at ZoneIndex " << grantedIndex
                      << "\n";
        }
    }

    for (const auto& configuration : configurations)
    {
        auto findZone =
            configuration.second.find(pidZoneConfigurationInterface);
        if (findZone != configuration.second.end())
        {
            const auto& zone = findZone->second;

            const std::string& name = std::get<std::string>(zone.at("Name"));

            auto index = getZoneIndex(name, foundZones);

            auto& details = zoneDetailsConfig[index];

            details.minThermalOutput = std::visit(VariantToDoubleVisitor(),
                                                  zone.at("MinThermalOutput"));

            int failsafepercent = 0;
            auto findFailSafe = zone.find("FailSafePercent");
            if (findFailSafe != zone.end())
            {
                failsafepercent = std::visit(VariantToDoubleVisitor(),
                                             zone.at("FailSafePercent"));
            }
            details.failsafePercent = failsafepercent;

            getCycleTimeSetting(zone, index, "CycleIntervalTimeMS",
                                details.cycleTime.cycleIntervalTimeMS);
            getCycleTimeSetting(zone, index, "UpdateThermalsTimeMS",
                                details.cycleTime.updateThermalsTimeMS);

            bool accumulateSetPoint = false;
            auto findAccSetPoint = zone.find("AccumulateSetPoint");
            if (findAccSetPoint != zone.end())
            {
                accumulateSetPoint = std::get<bool>(findAccSetPoint->second);
            }
            details.accumulateSetPoint = accumulateSetPoint;
        }
        auto findBase = configuration.second.find(pidConfigurationInterface);
        // loop through all the PID configurations and fill out a sensor config
        if (findBase != configuration.second.end())
        {
            const auto& base =
                configuration.second.at(pidConfigurationInterface);
            const std::string pidName =
                sensorNameToDbusName(std::get<std::string>(base.at("Name")));
            const std::string pidClass =
                std::get<std::string>(base.at("Class"));
            const std::vector<std::string>& zones =
                std::get<std::vector<std::string>>(base.at("Zones"));
            for (const std::string& zone : zones)
            {
                auto index = getZoneIndex(zone, foundZones);

                conf::PIDConf& conf = zoneConfig[index];
                std::vector<std::string> inputSensorNames(
                    std::get<std::vector<std::string>>(base.at("Inputs")));
                std::vector<std::string> outputSensorNames;
                std::vector<std::string> missingAcceptableSensorNames;
                std::vector<std::string> archivedInputSensorNames;

                auto findMissingAcceptable = base.find("MissingIsAcceptable");
                if (findMissingAcceptable != base.end())
                {
                    missingAcceptableSensorNames =
                        std::get<std::vector<std::string>>(
                            findMissingAcceptable->second);
                }

                // assumption: all fan pids must have at least one output
                if (pidClass == "fan")
                {
                    outputSensorNames = std::get<std::vector<std::string>>(
                        getPIDAttribute(base, "Outputs"));
                }

                bool unavailableAsFailed = true;
                auto findUnavailableAsFailed =
                    base.find("InputUnavailableAsFailed");
                if (findUnavailableAsFailed != base.end())
                {
                    unavailableAsFailed =
                        std::get<bool>(findUnavailableAsFailed->second);
                }

                std::vector<SensorInterfaceType> inputSensorInterfaces;
                std::vector<SensorInterfaceType> outputSensorInterfaces;
                std::vector<SensorInterfaceType>
                    missingAcceptableSensorInterfaces;

                /* populate an interface list for different sensor direction
                 * types (input,output)
                 */
                /* take the Inputs from the configuration and generate
                 * a list of dbus descriptors (path, interface).
                 * Mapping can be many-to-one since an element of Inputs can be
                 * a regex
                 */
                for (const std::string& sensorName : inputSensorNames)
                {
#ifndef HANDLE_MISSING_OBJECT_PATHS
                    findSensors(sensors, sensorNameToDbusName(sensorName),
                                inputSensorInterfaces);
#else
                    std::vector<std::pair<std::string, std::string>>
                        sensorPathIfacePairs;
                    auto found =
                        findSensors(sensors, sensorNameToDbusName(sensorName),
                                    sensorPathIfacePairs);
                    if (found)
                    {
                        inputSensorInterfaces.insert(
                            inputSensorInterfaces.end(),
                            sensorPathIfacePairs.begin(),
                            sensorPathIfacePairs.end());
                    }
                    else if (pidClass != "fan")
                    {
                        if (std::find(missingAcceptableSensorNames.begin(),
                                      missingAcceptableSensorNames.end(),
                                      sensorName) ==
                            missingAcceptableSensorNames.end())
                        {
                            std::cerr
                                << "Pid controller: Missing a missing-unacceptable sensor from D-Bus "
                                << sensorName << "\n";
                            std::string inputSensorName =
                                sensorNameToDbusName(sensorName);
                            auto& config = sensorConfig[inputSensorName];
                            archivedInputSensorNames.push_back(inputSensorName);
                            config.type = pidClass;
                            config.readPath =
                                getSensorPath(config.type, inputSensorName);
                            config.timeout = 0;
                            config.ignoreDbusMinMax = true;
                            config.unavailableAsFailed = unavailableAsFailed;
                        }
                        else
                        {
                            // When an input sensor is NOT on DBus, and it's in
                            // the MissingIsAcceptable list. Ignore it and
                            // continue with the next input sensor.
                            std::cout
                                << "Pid controller: Missing a missing-acceptable sensor from D-Bus "
                                << sensorName << "\n";
                            continue;
                        }
                    }
#endif
                }
                for (const std::string& sensorName : outputSensorNames)
                {
                    findSensors(sensors, sensorNameToDbusName(sensorName),
                                outputSensorInterfaces);
                }
                for (const std::string& sensorName :
                     missingAcceptableSensorNames)
                {
                    findSensors(sensors, sensorNameToDbusName(sensorName),
                                missingAcceptableSensorInterfaces);
                }

                for (const SensorInterfaceType& inputSensorInterface :
                     inputSensorInterfaces)
                {
                    const std::string& dbusInterface =
                        inputSensorInterface.second;
                    const std::string& inputSensorPath =
                        inputSensorInterface.first;

                    // Setting timeout to 0 is intentional, as D-Bus passive
                    // sensor updates are pushed in, not pulled by timer poll.
                    // Setting ignoreDbusMinMax is intentional, as this
                    // prevents normalization of values to [0.0, 1.0] range,
                    // which would mess up the PID loop math.
                    // All non-fan PID classes should be initialized this way.
                    // As for why a fan should not use this code path, see
                    // the ed1dafdf168def37c65bfb7a5efd18d9dbe04727 commit.
                    if ((pidClass == "temp") || (pidClass == "margin") ||
                        (pidClass == "power") || (pidClass == "powersum"))
                    {
                        std::string inputSensorName =
                            getSensorNameFromPath(inputSensorPath);
                        auto& config = sensorConfig[inputSensorName];
                        archivedInputSensorNames.push_back(inputSensorName);
                        config.type = pidClass;
                        config.readPath = inputSensorInterface.first;
                        config.timeout = 0;
                        config.ignoreDbusMinMax = true;
                        config.unavailableAsFailed = unavailableAsFailed;
                    }

                    if (dbusInterface != sensorInterface)
                    {
                        /* all expected inputs in the configuration are expected
                         * to be sensor interfaces
                         */
                        throw std::runtime_error(std::format(
                            "sensor at dbus path [{}] has an interface [{}] that does not match the expected interface of {}",
                            inputSensorPath, dbusInterface, sensorInterface));
                    }
                }

                // MissingIsAcceptable same postprocessing as Inputs
                missingAcceptableSensorNames.clear();
                for (const SensorInterfaceType&
                         missingAcceptableSensorInterface :
                     missingAcceptableSensorInterfaces)
                {
                    const std::string& dbusInterface =
                        missingAcceptableSensorInterface.second;
                    const std::string& missingAcceptableSensorPath =
                        missingAcceptableSensorInterface.first;

                    std::string missingAcceptableSensorName =
                        getSensorNameFromPath(missingAcceptableSensorPath);
                    missingAcceptableSensorNames.push_back(
                        missingAcceptableSensorName);

                    if (dbusInterface != sensorInterface)
                    {
                        /* MissingIsAcceptable same error checking as Inputs
                         */
                        throw std::runtime_error(std::format(
                            "sensor at dbus path [{}] has an interface [{}] that does not match the expected interface of {}",
                            missingAcceptableSensorPath, dbusInterface,
                            sensorInterface));
                    }
                }

                /* fan pids need to pair up tach sensors with their pwm
                 * counterparts
                 */
                if (pidClass == "fan")
                {
                    /* If a PID is a fan there should be either
                     * (1) one output(pwm) per input(tach)
                     * OR
                     * (2) one putput(pwm) for all inputs(tach)
                     * everything else indicates a bad configuration.
                     */
                    bool singlePwm = false;
                    if (outputSensorInterfaces.size() == 1)
                    {
                        /* one pwm, set write paths for all fan sensors to it */
                        singlePwm = true;
                    }
                    else if (inputSensorInterfaces.size() ==
                             outputSensorInterfaces.size())
                    {
                        /* one to one mapping, each fan sensor gets its own pwm
                         * control */
                        singlePwm = false;
                    }
                    else
                    {
                        throw std::runtime_error(
                            "fan PID has invalid number of Outputs");
                    }
                    std::string fanSensorName;
                    std::string pwmPath;
                    std::string pwmInterface;
                    std::string pwmSensorName;
                    if (singlePwm)
                    {
                        /* if just a single output(pwm) is provided then use
                         * that pwm control path for all the fan sensor write
                         * path configs
                         */
                        pwmPath = outputSensorInterfaces.at(0).first;
                        pwmInterface = outputSensorInterfaces.at(0).second;
                    }
                    for (uint32_t idx = 0; idx < inputSensorInterfaces.size();
                         idx++)
                    {
                        if (!singlePwm)
                        {
                            pwmPath = outputSensorInterfaces.at(idx).first;
                            pwmInterface =
                                outputSensorInterfaces.at(idx).second;
                        }
                        if (defaultPwmInterface != pwmInterface)
                        {
                            throw std::runtime_error(std::format(
                                "fan pwm control at dbus path [{}] has an interface [{}] that does not match the expected interface of {}",
                                pwmPath, pwmInterface, defaultPwmInterface));
                        }
                        const std::string& fanPath =
                            inputSensorInterfaces.at(idx).first;
                        fanSensorName = getSensorNameFromPath(fanPath);
                        pwmSensorName = getSensorNameFromPath(pwmPath);
                        std::string fanPwmIndex = fanSensorName + pwmSensorName;
                        archivedInputSensorNames.push_back(fanPwmIndex);
                        auto& fanConfig = sensorConfig[fanPwmIndex];
                        fanConfig.type = pidClass;
                        fanConfig.readPath = fanPath;
                        fanConfig.writePath = pwmPath;
                        // todo: un-hardcode this if there are fans with
                        // different ranges
                        fanConfig.max = 255;
                        fanConfig.min = 0;
                    }
                }
                // if the sensors aren't available in the current state, don't
                // add them to the configuration.
                if (archivedInputSensorNames.empty())
                {
                    continue;
                }

                std::string offsetType;

                // SetPointOffset is a threshold value to pull from the sensor
                // to apply an offset. For upper thresholds this means the
                // setpoint is usually negative.
                auto findSetpointOffset = base.find("SetPointOffset");
                if (findSetpointOffset != base.end())
                {
                    offsetType =
                        std::get<std::string>(findSetpointOffset->second);
                    if (std::find(thresholds::types.begin(),
                                  thresholds::types.end(), offsetType) ==
                        thresholds::types.end())
                    {
                        throw std::runtime_error(
                            "Unsupported type: " + offsetType);
                    }
                }

                std::vector<double> inputTempToMargin;

                auto findTempToMargin = base.find("TempToMargin");
                if (findTempToMargin != base.end())
                {
                    inputTempToMargin =
                        std::get<std::vector<double>>(findTempToMargin->second);
                }

                std::vector<pid_control::conf::SensorInput> sensorInputs =
                    spliceInputs(archivedInputSensorNames, inputTempToMargin,
                                 missingAcceptableSensorNames);

                if (offsetType.empty())
                {
                    conf::ControllerInfo& info = conf[pidName];
                    info.inputs = std::move(sensorInputs);
                    populatePidInfo(bus, base, info, nullptr, sensorConfig);
                }
                else
                {
                    // we have to split up the inputs, as in practice t-control
                    // values will differ, making setpoints differ
                    for (const pid_control::conf::SensorInput& input :
                         sensorInputs)
                    {
                        conf::ControllerInfo& info = conf[input.name];
                        info.inputs.emplace_back(input);
                        populatePidInfo(bus, base, info, &offsetType,
                                        sensorConfig);
                    }
                }
            }
        }
        auto findStepwise =
            configuration.second.find(stepwiseConfigurationInterface);
        if (findStepwise != configuration.second.end())
        {
            const auto& base = findStepwise->second;
            const std::string pidName =
                sensorNameToDbusName(std::get<std::string>(base.at("Name")));
            const std::vector<std::string>& zones =
                std::get<std::vector<std::string>>(base.at("Zones"));
            for (const std::string& zone : zones)
            {
                auto index = getZoneIndex(zone, foundZones);

                conf::PIDConf& conf = zoneConfig[index];

                std::vector<std::string> inputs;
                std::vector<std::string> missingAcceptableSensors;
                std::vector<std::string> missingAcceptableSensorNames;
                std::vector<std::string> sensorNames =
                    std::get<std::vector<std::string>>(base.at("Inputs"));

                auto findMissingAcceptable = base.find("MissingIsAcceptable");
                if (findMissingAcceptable != base.end())
                {
                    missingAcceptableSensorNames =
                        std::get<std::vector<std::string>>(
                            findMissingAcceptable->second);
                }

                bool unavailableAsFailed = true;
                auto findUnavailableAsFailed =
                    base.find("InputUnavailableAsFailed");
                if (findUnavailableAsFailed != base.end())
                {
                    unavailableAsFailed =
                        std::get<bool>(findUnavailableAsFailed->second);
                }

                bool sensorFound = false;
                for (const std::string& sensorName : sensorNames)
                {
                    std::vector<std::pair<std::string, std::string>>
                        sensorPathIfacePairs;
                    if (!findSensors(sensors, sensorNameToDbusName(sensorName),
                                     sensorPathIfacePairs))
                    {
#ifndef HANDLE_MISSING_OBJECT_PATHS
                        break;
#else
                        if (std::find(missingAcceptableSensorNames.begin(),
                                      missingAcceptableSensorNames.end(),
                                      sensorName) ==
                            missingAcceptableSensorNames.end())
                        {
                            // When an input sensor is NOT on DBus, and it's NOT
                            // in the MissingIsAcceptable list. Build it as a
                            // failed sensor with default information (temp
                            // sensor path, temp type, ...)
                            std::cerr
                                << "Stepwise controller: Missing a missing-unacceptable sensor from D-Bus "
                                << sensorName << "\n";
                            std::string shortName =
                                sensorNameToDbusName(sensorName);

                            inputs.push_back(shortName);
                            auto& config = sensorConfig[shortName];
                            config.type = "temp";
                            config.readPath =
                                getSensorPath(config.type, shortName);
                            config.ignoreDbusMinMax = true;
                            config.unavailableAsFailed = unavailableAsFailed;
                            // todo: maybe un-hardcode this if we run into
                            // slower timeouts with sensors

                            config.timeout = 0;
                            sensorFound = true;
                        }
                        else
                        {
                            // When an input sensor is NOT on DBus, and it's in
                            // the MissingIsAcceptable list. Ignore it and
                            // continue with the next input sensor.
                            std::cout
                                << "Stepwise controller: Missing a missing-acceptable sensor from D-Bus "
                                << sensorName << "\n";
                            continue;
                        }
#endif
                    }
                    else
                    {
                        for (const auto& sensorPathIfacePair :
                             sensorPathIfacePairs)
                        {
                            std::string shortName = getSensorNameFromPath(
                                sensorPathIfacePair.first);

                            inputs.push_back(shortName);
                            auto& config = sensorConfig[shortName];
                            config.readPath = sensorPathIfacePair.first;
                            config.type = "temp";
                            config.ignoreDbusMinMax = true;
                            config.unavailableAsFailed = unavailableAsFailed;
                            // todo: maybe un-hardcode this if we run into
                            // slower timeouts with sensors

                            config.timeout = 0;
                            sensorFound = true;
                        }
                    }
                }
                if (!sensorFound)
                {
                    continue;
                }

                // MissingIsAcceptable same postprocessing as Inputs
                for (const std::string& missingAcceptableSensorName :
                     missingAcceptableSensorNames)
                {
                    std::vector<std::pair<std::string, std::string>>
                        sensorPathIfacePairs;
                    if (!findSensors(
                            sensors,
                            sensorNameToDbusName(missingAcceptableSensorName),
                            sensorPathIfacePairs))
                    {
#ifndef HANDLE_MISSING_OBJECT_PATHS
                        break;
#else
                        // When a sensor in the MissingIsAcceptable list is NOT
                        // on DBus and it still reaches here, which contradicts
                        // to what we did in the Input sensor building step.
                        // Continue.
                        continue;
#endif
                    }

                    for (const auto& sensorPathIfacePair : sensorPathIfacePairs)
                    {
                        std::string shortName =
                            getSensorNameFromPath(sensorPathIfacePair.first);

                        missingAcceptableSensors.push_back(shortName);
                    }
                }

                conf::ControllerInfo& info = conf[pidName];

                std::vector<double> inputTempToMargin;

                auto findTempToMargin = base.find("TempToMargin");
                if (findTempToMargin != base.end())
                {
                    inputTempToMargin =
                        std::get<std::vector<double>>(findTempToMargin->second);
                }

                info.inputs = spliceInputs(inputs, inputTempToMargin,
                                           missingAcceptableSensors);

                info.type = "stepwise";
                info.stepwiseInfo.ts = 1.0; // currently unused
                info.stepwiseInfo.positiveHysteresis = 0.0;
                info.stepwiseInfo.negativeHysteresis = 0.0;
                std::string subtype = std::get<std::string>(base.at("Class"));

                info.stepwiseInfo.isCeiling = (subtype == "Ceiling");
                auto findPosHyst = base.find("PositiveHysteresis");
                auto findNegHyst = base.find("NegativeHysteresis");
                if (findPosHyst != base.end())
                {
                    info.stepwiseInfo.positiveHysteresis = std::visit(
                        VariantToDoubleVisitor(), findPosHyst->second);
                }
                if (findNegHyst != base.end())
                {
                    info.stepwiseInfo.negativeHysteresis = std::visit(
                        VariantToDoubleVisitor(), findNegHyst->second);
                }
                std::vector<double> readings =
                    std::get<std::vector<double>>(base.at("Reading"));
                if (readings.size() > ec::maxStepwisePoints)
                {
                    throw std::invalid_argument("Too many stepwise points.");
                }
                if (readings.empty())
                {
                    throw std::invalid_argument(
                        "Must have one stepwise point.");
                }
                std::copy(readings.begin(), readings.end(),
                          info.stepwiseInfo.reading);
                if (readings.size() < ec::maxStepwisePoints)
                {
                    info.stepwiseInfo.reading[readings.size()] =
                        std::numeric_limits<double>::quiet_NaN();
                }
                std::vector<double> outputs =
                    std::get<std::vector<double>>(base.at("Output"));
                if (readings.size() != outputs.size())
                {
                    throw std::invalid_argument(
                        "Outputs size must match readings");
                }
                std::copy(outputs.begin(), outputs.end(),
                          info.stepwiseInfo.output);
                if (outputs.size() < ec::maxStepwisePoints)
                {
                    info.stepwiseInfo.output[outputs.size()] =
                        std::numeric_limits<double>::quiet_NaN();
                }
            }
        }
    }
    if constexpr (pid_control::conf::DEBUG)
    {
        debugPrint(sensorConfig, zoneConfig, zoneDetailsConfig);
    }
    if (zoneConfig.empty() || zoneDetailsConfig.empty())
    {
        std::cerr
            << "No fan zones, application pausing until new configuration\n";
        return false;
    }
    return true;
}

} // namespace dbus_configuration
} // namespace pid_control
