/*
// Copyright (c) 2017 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 "DeviceMgmt.hpp"
#include "HwmonTempSensor.hpp"
#include "Utils.hpp"

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

#include <array>
#include <charconv>
#include <filesystem>
#include <fstream>
#include <functional>
#include <memory>
#include <regex>
#include <stdexcept>
#include <string>
#include <utility>
#include <variant>
#include <vector>

static constexpr float pollRateDefault = 0.5;

static constexpr double maxValuePressure = 120000; // Pascals
static constexpr double minValuePressure = 30000;  // Pascals

static constexpr double maxValueRelativeHumidity = 100; // PercentRH
static constexpr double minValueRelativeHumidity = 0;   // PercentRH

static constexpr double maxValueTemperature = 127;  // DegreesC
static constexpr double minValueTemperature = -128; // DegreesC

namespace fs = std::filesystem;

static const I2CDeviceTypeMap sensorTypes{
    {"DPS310", I2CDeviceType{"dps310", false}},
    {"EMC1412", I2CDeviceType{"emc1412", true}},
    {"EMC1413", I2CDeviceType{"emc1413", true}},
    {"EMC1414", I2CDeviceType{"emc1414", true}},
    {"HDC1080", I2CDeviceType{"hdc1080", false}},
    {"JC42", I2CDeviceType{"jc42", true}},
    {"LM75A", I2CDeviceType{"lm75a", true}},
    {"LM95234", I2CDeviceType{"lm95234", true}},
    {"MAX31725", I2CDeviceType{"max31725", true}},
    {"MAX31730", I2CDeviceType{"max31730", true}},
    {"MAX6581", I2CDeviceType{"max6581", true}},
    {"MAX6654", I2CDeviceType{"max6654", true}},
    {"NCT6779", I2CDeviceType{"nct6779", true}},
    {"NCT7802", I2CDeviceType{"nct7802", true}},
    {"SBTSI", I2CDeviceType{"sbtsi", true}},
    {"SI7020", I2CDeviceType{"si7020", false}},
    {"TMP100", I2CDeviceType{"tmp100", true}},
    {"TMP112", I2CDeviceType{"tmp112", true}},
    {"TMP175", I2CDeviceType{"tmp175", true}},
    {"TMP421", I2CDeviceType{"tmp421", true}},
    {"TMP441", I2CDeviceType{"tmp441", true}},
    {"TMP464", I2CDeviceType{"tmp464", true}},
    {"TMP75", I2CDeviceType{"tmp75", true}},
    {"W83773G", I2CDeviceType{"w83773g", true}},
};

static struct SensorParams
    getSensorParameters(const std::filesystem::path& path)
{
    // offset is to default to 0 and scale to 1, see lore
    // https://lore.kernel.org/linux-iio/5c79425f-6e88-36b6-cdfe-4080738d039f@metafoo.de/
    struct SensorParams tmpSensorParameters = {
        .minValue = minValueTemperature,
        .maxValue = maxValueTemperature,
        .offsetValue = 0.0,
        .scaleValue = 1.0,
        .units = sensor_paths::unitDegreesC,
        .typeName = "temperature"};

    // For IIO RAW sensors we get a raw_value, an offset, and scale
    // to compute the value = (raw_value + offset) * scale
    // with a _raw IIO device we need to get the
    // offsetValue and scaleValue from the driver
    // these are used to compute the reading in
    // units that have yet to be scaled for D-Bus.
    const std::string pathStr = path.string();
    if (pathStr.ends_with("_raw"))
    {
        std::string pathOffsetStr = pathStr.substr(0, pathStr.size() - 4) +
                                    "_offset";
        std::optional<double> tmpOffsetValue = readFile(pathOffsetStr, 1.0);
        // In case there is nothing to read skip this device
        // This is not an error condition see lore
        // https://lore.kernel.org/linux-iio/5c79425f-6e88-36b6-cdfe-4080738d039f@metafoo.de/
        if (tmpOffsetValue)
        {
            tmpSensorParameters.offsetValue = *tmpOffsetValue;
        }

        std::string pathScaleStr = pathStr.substr(0, pathStr.size() - 4) +
                                   "_scale";
        std::optional<double> tmpScaleValue = readFile(pathScaleStr, 1.0);
        // In case there is nothing to read skip this device
        // This is not an error condition see lore
        // https://lore.kernel.org/linux-iio/5c79425f-6e88-36b6-cdfe-4080738d039f@metafoo.de/
        if (tmpScaleValue)
        {
            tmpSensorParameters.scaleValue = *tmpScaleValue;
        }
    }

    // Temperatures are read in milli degrees Celsius, we need
    // degrees Celsius. Pressures are read in kilopascal, we need
    // Pascals.  On D-Bus for Open BMC we use the International
    // System of Units without prefixes. Links to the kernel
    // documentation:
    // https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
    // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-iio
    if (path.filename() == "in_pressure_input" ||
        path.filename() == "in_pressure_raw")
    {
        tmpSensorParameters.minValue = minValuePressure;
        tmpSensorParameters.maxValue = maxValuePressure;
        // Pressures are read in kilopascal, we need Pascals.
        tmpSensorParameters.scaleValue *= 1000.0;
        tmpSensorParameters.typeName = "pressure";
        tmpSensorParameters.units = sensor_paths::unitPascals;
    }
    else if (path.filename() == "in_humidityrelative_input" ||
             path.filename() == "in_humidityrelative_raw")
    {
        tmpSensorParameters.minValue = minValueRelativeHumidity;
        tmpSensorParameters.maxValue = maxValueRelativeHumidity;
        // Relative Humidity are read in milli-percent, we need percent.
        tmpSensorParameters.scaleValue *= 0.001;
        tmpSensorParameters.typeName = "humidity";
        tmpSensorParameters.units = "PercentRH";
    }
    else
    {
        // Temperatures are read in milli degrees Celsius,
        // we need degrees Celsius.
        tmpSensorParameters.scaleValue *= 0.001;
    }

    return tmpSensorParameters;
}

struct SensorConfigKey
{
    uint64_t bus;
    uint64_t addr;
    bool operator<(const SensorConfigKey& other) const
    {
        if (bus != other.bus)
        {
            return bus < other.bus;
        }
        return addr < other.addr;
    }
};

struct SensorConfig
{
    std::string sensorPath;
    SensorData sensorData;
    std::string interface;
    SensorBaseConfigMap config;
    std::vector<std::string> name;
};

using SensorConfigMap =
    boost::container::flat_map<SensorConfigKey, SensorConfig>;

static SensorConfigMap
    buildSensorConfigMap(const ManagedObjectType& sensorConfigs)
{
    SensorConfigMap configMap;
    for (const auto& [path, cfgData] : sensorConfigs)
    {
        for (const auto& [intf, cfg] : cfgData)
        {
            auto busCfg = cfg.find("Bus");
            auto addrCfg = cfg.find("Address");
            if ((busCfg == cfg.end()) || (addrCfg == cfg.end()))
            {
                continue;
            }

            if ((std::get_if<uint64_t>(&busCfg->second) == nullptr) ||
                (std::get_if<uint64_t>(&addrCfg->second) == nullptr))
            {
                std::cerr << path.str << " Bus or Address invalid\n";
                continue;
            }

            std::vector<std::string> hwmonNames;
            auto nameCfg = cfg.find("Name");
            if (nameCfg != cfg.end())
            {
                hwmonNames.push_back(std::get<std::string>(nameCfg->second));
                size_t i = 1;
                while (true)
                {
                    auto sensorNameCfg = cfg.find("Name" + std::to_string(i));
                    if (sensorNameCfg == cfg.end())
                    {
                        break;
                    }
                    hwmonNames.push_back(
                        std::get<std::string>(sensorNameCfg->second));
                    i++;
                }
            }

            SensorConfigKey key = {std::get<uint64_t>(busCfg->second),
                                   std::get<uint64_t>(addrCfg->second)};
            SensorConfig val = {path.str, cfgData, intf, cfg, hwmonNames};

            auto [it, inserted] = configMap.emplace(key, std::move(val));
            if (!inserted)
            {
                std::cerr << path.str << ": ignoring duplicate entry for {"
                          << key.bus << ", 0x" << std::hex << key.addr
                          << std::dec << "}\n";
            }
        }
    }
    return configMap;
}

// returns a {path: <I2CDevice, is_new>} map.  is_new indicates if the I2CDevice
// is newly instantiated by this call (true) or was already there (false).
boost::container::flat_map<std::string,
                           std::pair<std::shared_ptr<I2CDevice>, bool>>
    instantiateDevices(
        const ManagedObjectType& sensorConfigs,
        const boost::container::flat_map<
            std::string, std::shared_ptr<HwmonTempSensor>>& sensors)
{
    boost::container::flat_map<std::string,
                               std::pair<std::shared_ptr<I2CDevice>, bool>>
        devices;
    for (const auto& [path, sensor] : sensorConfigs)
    {
        for (const auto& [name, cfg] : sensor)
        {
            PowerState powerState = getPowerState(cfg);
            if (!readingStateGood(powerState))
            {
                continue;
            }

            auto findSensorName = cfg.find("Name");
            if (findSensorName == cfg.end())
            {
                continue;
            }
            std::string sensorName =
                std::get<std::string>(findSensorName->second);

            auto findSensor = sensors.find(sensorName);
            if (findSensor != sensors.end() && findSensor->second != nullptr &&
                findSensor->second->isActive())
            {
                devices.emplace(
                    path.str,
                    std::make_pair(findSensor->second->getI2CDevice(), false));
                continue;
            }

            std::optional<I2CDeviceParams> params =
                getI2CDeviceParams(sensorTypes, cfg);
            if (params.has_value() && !params->deviceStatic())
            {
                // There exist error cases in which a sensor device that we
                // need is already instantiated, but needs to be destroyed and
                // re-created in order to be useful (for example if we crash
                // after instantiating a device and the sensor device's power
                // is cut before we get restarted, leaving it "present" but
                // not really usable).  To be on the safe side, instantiate a
                // temporary device that's immediately destroyed so as to
                // ensure that we end up with a fresh instance of it.
                if (params->devicePresent())
                {
                    std::cerr << "Clearing out previous instance for "
                              << path.str << "\n";
                    I2CDevice tmp(*params);
                }

                try
                {
                    devices.emplace(
                        path.str,
                        std::make_pair(std::make_shared<I2CDevice>(*params),
                                       true));
                }
                catch (std::runtime_error&)
                {
                    std::cerr << "Failed to instantiate " << params->type->name
                              << " at address " << params->address << " on bus "
                              << params->bus << "\n";
                }
            }
        }
    }
    return devices;
}

void createSensors(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
    boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>&
        sensors,
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
    const std::shared_ptr<boost::container::flat_set<std::string>>&
        sensorsChanged,
    bool activateOnly)
{
    auto getter = std::make_shared<GetSensorConfiguration>(
        dbusConnection,
        [&io, &objectServer, &sensors, &dbusConnection, sensorsChanged,
         activateOnly](const ManagedObjectType& sensorConfigurations) {
        bool firstScan = sensorsChanged == nullptr;

        SensorConfigMap configMap = buildSensorConfigMap(sensorConfigurations);

        auto devices = instantiateDevices(sensorConfigurations, sensors);

        // IIO _raw devices look like this on sysfs:
        //     /sys/bus/iio/devices/iio:device0/in_temp_raw
        //     /sys/bus/iio/devices/iio:device0/in_temp_offset
        //     /sys/bus/iio/devices/iio:device0/in_temp_scale
        //
        // Other IIO devices look like this on sysfs:
        //     /sys/bus/iio/devices/iio:device1/in_temp_input
        //     /sys/bus/iio/devices/iio:device1/in_pressure_input
        std::vector<fs::path> paths;
        fs::path root("/sys/bus/iio/devices");
        findFiles(root, R"(in_temp\d*_(input|raw))", paths);
        findFiles(root, R"(in_pressure\d*_(input|raw))", paths);
        findFiles(root, R"(in_humidityrelative\d*_(input|raw))", paths);
        findFiles(fs::path("/sys/class/hwmon"), R"(temp\d+_input)", paths);

        // iterate through all found temp and pressure sensors,
        // and try to match them with configuration
        for (auto& path : paths)
        {
            std::smatch match;
            const std::string pathStr = path.string();
            auto directory = path.parent_path();
            fs::path device;

            std::string deviceName;
            if (pathStr.starts_with("/sys/bus/iio/devices"))
            {
                device = fs::canonical(directory);
                deviceName = device.parent_path().stem();
            }
            else
            {
                device = directory / "device";
                deviceName = fs::canonical(device).stem();
            }
            auto findHyphen = deviceName.find('-');
            if (findHyphen == std::string::npos)
            {
                std::cerr << "found bad device " << deviceName << "\n";
                continue;
            }
            std::string busStr = deviceName.substr(0, findHyphen);
            std::string addrStr = deviceName.substr(findHyphen + 1);

            uint64_t bus = 0;
            uint64_t addr = 0;
            std::from_chars_result res{};
            res = std::from_chars(busStr.data(), busStr.data() + busStr.size(),
                                  bus);
            if (res.ec != std::errc{})
            {
                continue;
            }
            res = std::from_chars(addrStr.data(),
                                  addrStr.data() + addrStr.size(), addr, 16);
            if (res.ec != std::errc{})
            {
                continue;
            }

            auto thisSensorParameters = getSensorParameters(path);
            auto findSensorCfg = configMap.find({bus, addr});
            if (findSensorCfg == configMap.end())
            {
                continue;
            }

            const std::string& interfacePath = findSensorCfg->second.sensorPath;
            auto findI2CDev = devices.find(interfacePath);

            std::shared_ptr<I2CDevice> i2cDev;
            if (findI2CDev != devices.end())
            {
                // If we're only looking to activate newly-instantiated i2c
                // devices and this sensor's underlying device was already there
                // before this call, there's nothing more to do here.
                if (activateOnly && !findI2CDev->second.second)
                {
                    continue;
                }
                i2cDev = findI2CDev->second.first;
            }

            const SensorData& sensorData = findSensorCfg->second.sensorData;
            std::string sensorType = findSensorCfg->second.interface;
            auto pos = sensorType.find_last_of('.');
            if (pos != std::string::npos)
            {
                sensorType = sensorType.substr(pos + 1);
            }
            const SensorBaseConfigMap& baseConfigMap =
                findSensorCfg->second.config;
            std::vector<std::string>& hwmonName = findSensorCfg->second.name;

            // Temperature has "Name", pressure has "Name1"
            auto findSensorName = baseConfigMap.find("Name");
            int index = 1;
            if (thisSensorParameters.typeName == "pressure" ||
                thisSensorParameters.typeName == "humidity")
            {
                findSensorName = baseConfigMap.find("Name1");
                index = 2;
            }

            if (findSensorName == baseConfigMap.end())
            {
                std::cerr << "could not determine configuration name for "
                          << deviceName << "\n";
                continue;
            }
            std::string sensorName =
                std::get<std::string>(findSensorName->second);
            // on rescans, only update sensors we were signaled by
            auto findSensor = sensors.find(sensorName);
            if (!firstScan && findSensor != sensors.end())
            {
                bool found = false;
                auto it = sensorsChanged->begin();
                while (it != sensorsChanged->end())
                {
                    if (it->ends_with(findSensor->second->name))
                    {
                        it = sensorsChanged->erase(it);
                        findSensor->second = nullptr;
                        found = true;
                        break;
                    }
                    ++it;
                }
                if (!found)
                {
                    continue;
                }
            }

            std::vector<thresholds::Threshold> sensorThresholds;

            if (!parseThresholdsFromConfig(sensorData, sensorThresholds,
                                           nullptr, &index))
            {
                std::cerr << "error populating thresholds for " << sensorName
                          << " index " << index << "\n";
            }

            float pollRate = getPollRate(baseConfigMap, pollRateDefault);
            PowerState readState = getPowerState(baseConfigMap);

            auto permitSet = getPermitSet(baseConfigMap);
            auto& sensor = sensors[sensorName];
            if (!activateOnly)
            {
                sensor = nullptr;
            }
            auto hwmonFile = getFullHwmonFilePath(directory.string(), "temp1",
                                                  permitSet);
            if (pathStr.starts_with("/sys/bus/iio/devices"))
            {
                hwmonFile = pathStr;
            }
            if (hwmonFile)
            {
                if (sensor != nullptr)
                {
                    sensor->activate(*hwmonFile, i2cDev);
                }
                else
                {
                    sensor = std::make_shared<HwmonTempSensor>(
                        *hwmonFile, sensorType, objectServer, dbusConnection,
                        io, sensorName, std::move(sensorThresholds),
                        thisSensorParameters, pollRate, interfacePath,
                        readState, i2cDev);
                    sensor->setupRead();
                }
            }
            hwmonName.erase(
                remove(hwmonName.begin(), hwmonName.end(), sensorName),
                hwmonName.end());

            // Looking for keys like "Name1" for temp2_input,
            // "Name2" for temp3_input, etc.
            int i = 0;
            while (true)
            {
                ++i;
                auto findKey = baseConfigMap.find("Name" + std::to_string(i));
                if (findKey == baseConfigMap.end())
                {
                    break;
                }
                std::string sensorName = std::get<std::string>(findKey->second);
                hwmonFile = getFullHwmonFilePath(directory.string(),
                                                 "temp" + std::to_string(i + 1),
                                                 permitSet);
                if (pathStr.starts_with("/sys/bus/iio/devices"))
                {
                    continue;
                }
                if (hwmonFile)
                {
                    // To look up thresholds for these additional sensors,
                    // match on the Index property in the threshold data
                    // where the index comes from the sysfs file we're on,
                    // i.e. index = 2 for temp2_input.
                    int index = i + 1;
                    std::vector<thresholds::Threshold> thresholds;

                    if (!parseThresholdsFromConfig(sensorData, thresholds,
                                                   nullptr, &index))
                    {
                        std::cerr << "error populating thresholds for "
                                  << sensorName << " index " << index << "\n";
                    }

                    auto& sensor = sensors[sensorName];
                    if (!activateOnly)
                    {
                        sensor = nullptr;
                    }

                    if (sensor != nullptr)
                    {
                        sensor->activate(*hwmonFile, i2cDev);
                    }
                    else
                    {
                        sensor = std::make_shared<HwmonTempSensor>(
                            *hwmonFile, sensorType, objectServer,
                            dbusConnection, io, sensorName,
                            std::move(thresholds), thisSensorParameters,
                            pollRate, interfacePath, readState, i2cDev);
                        sensor->setupRead();
                    }
                }

                hwmonName.erase(
                    remove(hwmonName.begin(), hwmonName.end(), sensorName),
                    hwmonName.end());
            }
            if (hwmonName.empty())
            {
                configMap.erase(findSensorCfg);
            }
        }
        });
    std::vector<std::string> types(sensorTypes.size());
    for (const auto& [type, dt] : sensorTypes)
    {
        types.push_back(type);
    }
    getter->getConfiguration(types);
}

void interfaceRemoved(
    sdbusplus::message_t& message,
    boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>&
        sensors)
{
    if (message.is_method_error())
    {
        std::cerr << "interfacesRemoved callback method error\n";
        return;
    }

    sdbusplus::message::object_path path;
    std::vector<std::string> interfaces;

    message.read(path, interfaces);

    // If the xyz.openbmc_project.Confguration.X interface was removed
    // for one or more sensors, delete those sensor objects.
    auto sensorIt = sensors.begin();
    while (sensorIt != sensors.end())
    {
        if ((sensorIt->second->configurationPath == path) &&
            (std::find(interfaces.begin(), interfaces.end(),
                       sensorIt->second->configInterface) != interfaces.end()))
        {
            sensorIt = sensors.erase(sensorIt);
        }
        else
        {
            sensorIt++;
        }
    }
}

static void powerStateChanged(
    PowerState type, bool newState,
    boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>&
        sensors,
    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
{
    if (newState)
    {
        createSensors(io, objectServer, sensors, dbusConnection, nullptr, true);
    }
    else
    {
        for (auto& [path, sensor] : sensors)
        {
            if (sensor != nullptr && sensor->readState == type)
            {
                sensor->deactivate();
            }
        }
    }
}

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.HwmonTempSensor");

    boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>
        sensors;
    auto sensorsChanged =
        std::make_shared<boost::container::flat_set<std::string>>();

    auto powerCallBack = [&sensors, &io, &objectServer,
                          &systemBus](PowerState type, bool state) {
        powerStateChanged(type, state, sensors, io, objectServer, systemBus);
    };
    setupPowerMatchCallback(systemBus, powerCallBack);

    boost::asio::post(io, [&]() {
        createSensors(io, objectServer, sensors, systemBus, nullptr, false);
    });

    boost::asio::steady_timer filterTimer(io);
    std::function<void(sdbusplus::message_t&)> eventHandler =
        [&](sdbusplus::message_t& message) {
        if (message.is_method_error())
        {
            std::cerr << "callback method error\n";
            return;
        }
        sensorsChanged->insert(message.get_path());
        // this implicitly cancels the timer
        filterTimer.expires_after(std::chrono::seconds(1));

        filterTimer.async_wait([&](const boost::system::error_code& ec) {
            if (ec == boost::asio::error::operation_aborted)
            {
                /* we were canceled*/
                return;
            }
            if (ec)
            {
                std::cerr << "timer error\n";
                return;
            }
            createSensors(io, objectServer, sensors, systemBus, sensorsChanged,
                          false);
        });
    };

    std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
        setupPropertiesChangedMatches(*systemBus, sensorTypes, eventHandler);
    setupManufacturingModeMatch(*systemBus);

    // Watch for entity-manager to remove configuration interfaces
    // so the corresponding sensors can be removed.
    auto ifaceRemovedMatch = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        "type='signal',member='InterfacesRemoved',arg0path='" +
            std::string(inventoryPath) + "/'",
        [&sensors](sdbusplus::message_t& msg) {
        interfaceRemoved(msg, sensors);
        });

    matches.emplace_back(std::move(ifaceRemovedMatch));

    io.run();
}
