/*
// 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 "SensorPaths.hpp"
#include "Thresholds.hpp"
#include "Utils.hpp"

#include <boost/asio/error.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/steady_timer.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.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/message/native_types.hpp>

#include <algorithm>
#include <array>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <functional>
#include <ios>
#include <iostream>
#include <memory>
#include <optional>
#include <regex>
#include <string>
#include <system_error>
#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{
    {"ADM1021", I2CDeviceType{"adm1021", true}},
    {"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}},
    {"MAX6639", I2CDeviceType{"max6639", true}},
    {"MCP9600", I2CDeviceType{"mcp9600", false}},
    {"NCT6779", I2CDeviceType{"nct6779", true}},
    {"NCT7802", I2CDeviceType{"nct7802", true}},
    {"PT5161L", I2CDeviceType{"pt5161l", 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}},
    {"TMP461", I2CDeviceType{"tmp461", 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 = sensor_paths::unitPercentRH;
    }
    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;
}

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,
                                          sensorTypes);

        // 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;
            std::error_code ec;
            if (pathStr.starts_with("/sys/bus/iio/devices"))
            {
                device = fs::canonical(directory, ec);
                if (ec)
                {
                    std::cerr << "Fail to find device in path [" << pathStr
                              << "]\n";
                    continue;
                }
                deviceName = device.parent_path().stem();
            }
            else
            {
                device = fs::canonical(directory / "device", ec);
                if (ec)
                {
                    std::cerr << "Fail to find device in path [" << pathStr
                              << "]\n";
                    continue;
                }
                deviceName = device.stem();
            }

            uint64_t bus = 0;
            uint64_t addr = 0;
            if (!getDeviceBusAddr(deviceName, bus, addr))
            {
                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 && (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();
}
