#pragma once

#include "config.h"

#include "sensorhandler.hpp"

#include <cmath>
#include <ipmid/api.hpp>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/message/types.hpp>

#ifdef FEATURE_SENSORS_CACHE

extern ipmi::sensor::SensorCacheMap sensorCacheMap;

// The signal's message type is 0x04 from DBus spec:
// https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
static constexpr auto msgTypeSignal = 0x04;

#endif

namespace ipmi
{
namespace sensor
{

using Assertion = uint16_t;
using Deassertion = uint16_t;
using AssertionSet = std::pair<Assertion, Deassertion>;

using Service = std::string;
using Path = std::string;
using Interface = std::string;

using ServicePath = std::pair<Path, Service>;

using Interfaces = std::vector<Interface>;

using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
using namespace phosphor::logging;

/** @brief get the D-Bus service and service path
 *  @param[in] bus - The Dbus bus object
 *  @param[in] interface - interface to the service
 *  @param[in] path - interested path in the list of objects
 *  @return pair of service path and service
 */
ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
                              const std::string& interface,
                              const std::string& path = std::string());

/** @brief Make assertion set from input data
 *  @param[in] cmdData - Input sensor data
 *  @return pair of assertion and deassertion set
 */
AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData);

/** @brief send the message to DBus
 *  @param[in] msg - message to send
 *  @return failure status in IPMI error code
 */
ipmi_ret_t updateToDbus(IpmiUpdateData& msg);

namespace get
{

/** @brief Populate sensor name from the D-Bus property associated with the
 *         sensor. In the example entry from the yaml, the name of the D-bus
 *         property "AttemptsLeft" is the sensor name.
 *
 *         0x07:
 *            sensorType: 195
 *            path: /xyz/openbmc_project/state/host0
 *            sensorReadingType: 0x6F
 *            serviceInterface: org.freedesktop.DBus.Properties
 *            readingType: readingAssertion
 *            sensorNamePattern: nameProperty
 *            interfaces:
 *              xyz.openbmc_project.Control.Boot.RebootAttempts:
 *                AttemptsLeft:
 *                    Offsets:
 *                        0xFF:
 *                          type: uint32_t
 *
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return On success return the sensor name for the sensor.
 */
inline SensorName nameProperty(const Info& sensorInfo)
{
    return sensorInfo.propertyInterfaces.begin()->second.begin()->first;
}

/** @brief Populate sensor name from the D-Bus object associated with the
 *         sensor. If the object path is /system/chassis/motherboard/dimm0 then
 *         the leaf dimm0 is considered as the sensor name.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return On success return the sensor name for the sensor.
 */
inline SensorName nameLeaf(const Info& sensorInfo)
{
    return sensorInfo.sensorPath.substr(
        sensorInfo.sensorPath.find_last_of('/') + 1,
        sensorInfo.sensorPath.length());
}

/** @brief Populate sensor name from the D-Bus object associated with the
 *         sensor and the property.
 *         If the object path is /xyz/openbmc_project/inventory/Fan0 and
 *         the property is Present, the leaf Fan0 and the Property is
 *         joined to Fan0_Present as the sensor name.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return On success return the sensor name for the sensor.
 */
inline SensorName nameLeafProperty(const Info& sensorInfo)
{
    return nameLeaf(sensorInfo) + "_" + nameProperty(sensorInfo);
}

/** @brief Populate sensor name from the D-Bus object associated with the
 *         sensor. If the object path is /system/chassis/motherboard/cpu0/core0
 *         then the sensor name is cpu0_core0. The leaf and the parent is put
 *         together to get the sensor name.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return On success return the sensor name for the sensor.
 */
SensorName nameParentLeaf(const Info& sensorInfo);

/**
 *  @brief Helper function to map the dbus info to sensor's assertion status
 *         for the get sensor reading command.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *  @param[in] path - Dbus object path.
 *  @param[in] interface - Dbus interface.
 *
 *  @return Response for get sensor reading command.
 */
GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
                                     const InstancePath& path,
                                     const DbusInterface& interface);

#ifndef FEATURE_SENSORS_CACHE
/**
 *  @brief Map the Dbus info to sensor's assertion status in the Get sensor
 *         reading command response.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return Response for get sensor reading command.
 */
GetSensorResponse assertion(const Info& sensorInfo);

/**
 *  @brief Maps the Dbus info to the reading field in the Get sensor reading
 *         command response.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return Response for get sensor reading command.
 */
GetSensorResponse eventdata2(const Info& sensorInfo);

/**
 *  @brief readingAssertion is a case where the entire assertion state field
 *         serves as the sensor value.
 *
 *  @tparam T - type of the dbus property related to sensor.
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return Response for get sensor reading command.
 */
template <typename T>
GetSensorResponse readingAssertion(const Info& sensorInfo)
{
    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
    GetSensorResponse response{};

    enableScanning(&response);

    auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
                                    sensorInfo.sensorPath);

    auto propValue = ipmi::getDbusProperty(
        bus, service, sensorInfo.sensorPath,
        sensorInfo.propertyInterfaces.begin()->first,
        sensorInfo.propertyInterfaces.begin()->second.begin()->first);

    setAssertionBytes(static_cast<uint16_t>(std::get<T>(propValue)), &response);

    return response;
}

/** @brief Map the Dbus info to the reading field in the Get sensor reading
 *         command response
 *
 *  @tparam T - type of the dbus property related to sensor.
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return Response for get sensor reading command.
 */
template <typename T>
GetSensorResponse readingData(const Info& sensorInfo)
{
    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};

    GetSensorResponse response{};

    enableScanning(&response);

    auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
                                    sensorInfo.sensorPath);

#ifdef UPDATE_FUNCTIONAL_ON_FAIL
    // Check the OperationalStatus interface for functional property
    if (sensorInfo.propertyInterfaces.begin()->first ==
        "xyz.openbmc_project.Sensor.Value")
    {
        bool functional = true;
        try
        {
            auto funcValue = ipmi::getDbusProperty(
                bus, service, sensorInfo.sensorPath,
                "xyz.openbmc_project.State.Decorator.OperationalStatus",
                "Functional");
            functional = std::get<bool>(funcValue);
        }
        catch (...)
        {
            // No-op if Functional property could not be found since this
            // check is only valid for Sensor.Value read for hwmonio
        }
        if (!functional)
        {
            throw SensorFunctionalError();
        }
    }
#endif

    auto propValue = ipmi::getDbusProperty(
        bus, service, sensorInfo.sensorPath,
        sensorInfo.propertyInterfaces.begin()->first,
        sensorInfo.propertyInterfaces.begin()->second.begin()->first);

    double value = std::get<T>(propValue) *
                   std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
    int32_t rawData =
        (value - sensorInfo.scaledOffset) / sensorInfo.coefficientM;

    constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
    constexpr uint8_t signedDataFormat = 0x80;
    // if sensorUnits1 [7:6] = 10b, sensor is signed
    if ((sensorInfo.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
    {
        if (rawData > std::numeric_limits<int8_t>::max() ||
            rawData < std::numeric_limits<int8_t>::lowest())
        {
            log<level::ERR>("Value out of range");
            throw std::out_of_range("Value out of range");
        }
        setReading(static_cast<int8_t>(rawData), &response);
    }
    else
    {
        if (rawData > std::numeric_limits<uint8_t>::max() ||
            rawData < std::numeric_limits<uint8_t>::lowest())
        {
            log<level::ERR>("Value out of range");
            throw std::out_of_range("Value out of range");
        }
        setReading(static_cast<uint8_t>(rawData), &response);
    }

    if (!std::isfinite(value))
    {
        response.readingOrStateUnavailable = 1;
    }

    bool critAlarmHigh;
    try
    {
        critAlarmHigh = std::get<bool>(ipmi::getDbusProperty(
            bus, service, sensorInfo.sensorPath,
            "xyz.openbmc_project.Sensor.Threshold.Critical",
            "CriticalAlarmHigh"));
    }
    catch (const std::exception& e)
    {
        critAlarmHigh = false;
    }
    bool critAlarmLow;
    try
    {
        critAlarmLow = std::get<bool>(ipmi::getDbusProperty(
            bus, service, sensorInfo.sensorPath,
            "xyz.openbmc_project.Sensor.Threshold.Critical",
            "CriticalAlarmLow"));
    }
    catch (const std::exception& e)
    {
        critAlarmLow = false;
    }
    bool warningAlarmHigh;
    try
    {
        warningAlarmHigh = std::get<bool>(ipmi::getDbusProperty(
            bus, service, sensorInfo.sensorPath,
            "xyz.openbmc_project.Sensor.Threshold.Warning",
            "WarningAlarmHigh"));
    }
    catch (const std::exception& e)
    {
        warningAlarmHigh = false;
    }
    bool warningAlarmLow;
    try
    {
        warningAlarmLow = std::get<bool>(ipmi::getDbusProperty(
            bus, service, sensorInfo.sensorPath,
            "xyz.openbmc_project.Sensor.Threshold.Warning", "WarningAlarmlow"));
    }
    catch (const std::exception& e)
    {
        warningAlarmLow = false;
    }
    response.thresholdLevelsStates =
        (static_cast<uint8_t>(critAlarmHigh) << 4) |
        (static_cast<uint8_t>(warningAlarmHigh) << 3) |
        (static_cast<uint8_t>(warningAlarmLow) << 2) |
        (static_cast<uint8_t>(critAlarmLow) << 1);

    return response;
}

#else

/**
 *  @brief Map the Dbus info to sensor's assertion status in the Get sensor
 *         reading command response.
 *
 *  @param[in] id - The sensor id
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *  @param[in] msg - Dbus message from match callback.
 *
 *  @return Response for get sensor reading command.
 */
std::optional<GetSensorResponse> assertion(uint8_t id, const Info& sensorInfo,
                                           sdbusplus::message::message& msg);

/**
 *  @brief Maps the Dbus info to the reading field in the Get sensor reading
 *         command response.
 *
 *  @param[in] id - The sensor id
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *  @param[in] msg - Dbus message from match callback.
 *
 *  @return Response for get sensor reading command.
 */
std::optional<GetSensorResponse> eventdata2(uint8_t id, const Info& sensorInfo,
                                            sdbusplus::message::message& msg);

/**
 *  @brief readingAssertion is a case where the entire assertion state field
 *         serves as the sensor value.
 *
 *  @tparam T - type of the dbus property related to sensor.
 *  @param[in] id - The sensor id
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *  @param[in] msg - Dbus message from match callback.
 *
 *  @return Response for get sensor reading command.
 */
template <typename T>
std::optional<GetSensorResponse>
    readingAssertion(uint8_t id, const Info& sensorInfo,
                     sdbusplus::message::message& msg)
{
    auto type = msg.get_type();
    if (type == msgTypeSignal)
    {
        // This is signal callback
        std::string interfaceName;
        msg.read(interfaceName);
        if (interfaceName != sensorInfo.sensorInterface)
        {
            // Not the interface we need
            return {};
        }
    }
    // Now the message only contains the properties.
    GetSensorResponse response{};
    std::map<std::string, ipmi::Value> properties;

    enableScanning(&response);

    msg.read(properties);

    auto iter = properties.find(
        sensorInfo.propertyInterfaces.begin()->second.begin()->first);
    if (iter == properties.end())
    {
        return {};
    }

    setAssertionBytes(static_cast<uint16_t>(std::get<T>(iter->second)),
                      &response);

    if (!sensorCacheMap[id].has_value())
    {
        sensorCacheMap[id] = SensorData{};
    }
    sensorCacheMap[id]->response = response;
    return response;
}

/** @brief Get sensor reading from the dbus message from match
 *
 *  @tparam T - type of the dbus property related to sensor.
 *  @param[in] id - The sensor id
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *  @param[in] msg - Dbus message from match callback.
 *
 *  @return Response for get sensor reading command.
 */
template <typename T>
std::optional<GetSensorResponse> readingData(uint8_t id, const Info& sensorInfo,
                                             sdbusplus::message::message& msg)
{
    std::map<std::string, ipmi::Value> properties;
    auto type = msg.get_type();
    if (type == msgTypeSignal)
    {
        // This is signal callback
        std::string interfaceName;
        msg.read(interfaceName);

        if (interfaceName ==
            "xyz.openbmc_project.State.Decorator.OperationalStatus")
        {
            msg.read(properties);
            auto val = properties.find("Functional");
            if (val != properties.end())
            {
                sensorCacheMap[id]->functional = std::get<bool>(val->second);
            }
            return {};
        }
        if (interfaceName == "xyz.openbmc_project.State.Decorator.Availability")
        {
            msg.read(properties);
            auto val = properties.find("Available");
            if (val != properties.end())
            {
                sensorCacheMap[id]->available = std::get<bool>(val->second);
            }
            return {};
        }

        if (interfaceName != sensorInfo.sensorInterface)
        {
            // Not the interface we need
            return {};
        }

#ifdef UPDATE_FUNCTIONAL_ON_FAIL
        if (sensorCacheMap[id])
        {
            if (!sensorCacheMap[id]->functional)
            {
                throw SensorFunctionalError();
            }
        }
#endif
    }
    // Now the message only contains the properties.

    GetSensorResponse response{};

    enableScanning(&response);

    msg.read(properties);

    auto iter = properties.find(
        sensorInfo.propertyInterfaces.begin()->second.begin()->first);
    if (iter == properties.end())
    {
        return {};
    }

    double value = std::get<T>(iter->second) *
                   std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
    int32_t rawData =
        (value - sensorInfo.scaledOffset) / sensorInfo.coefficientM;

    constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
    constexpr uint8_t signedDataFormat = 0x80;
    // if sensorUnits1 [7:6] = 10b, sensor is signed
    if ((sensorInfo.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
    {
        if (rawData > std::numeric_limits<int8_t>::max() ||
            rawData < std::numeric_limits<int8_t>::lowest())
        {
            log<level::ERR>("Value out of range");
            throw std::out_of_range("Value out of range");
        }
        setReading(static_cast<int8_t>(rawData), &response);
    }
    else
    {
        if (rawData > std::numeric_limits<uint8_t>::max() ||
            rawData < std::numeric_limits<uint8_t>::lowest())
        {
            log<level::ERR>("Value out of range");
            throw std::out_of_range("Value out of range");
        }
        setReading(static_cast<uint8_t>(rawData), &response);
    }

    if (!std::isfinite(value))
    {
        response.readingOrStateUnavailable = 1;
    }

    if (!sensorCacheMap[id].has_value())
    {
        sensorCacheMap[id] = SensorData{};
    }
    sensorCacheMap[id]->response = response;

    return response;
}

#endif // FEATURE_SENSORS_CACHE

} // namespace get

namespace set
{

/** @brief Make a DBus message for a Dbus call
 *  @param[in] updateInterface - Interface name
 *  @param[in] sensorPath - Path of the sensor
 *  @param[in] command - command to be executed
 *  @param[in] sensorInterface - DBus interface of sensor
 *  @return a dbus message
 */
IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
                           const std::string& sensorPath,
                           const std::string& command,
                           const std::string& sensorInterface);

/** @brief Update d-bus based on assertion type sensor data
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
                     const Info& sensorInfo);

/** @brief Update d-bus based on a reading assertion
 *  @tparam T - type of d-bus property mapping this sensor
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
template <typename T>
ipmi_ret_t readingAssertion(const SetSensorReadingReq& cmdData,
                            const Info& sensorInfo)
{
    auto msg =
        makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
                    "Set", sensorInfo.sensorInterface);

    const auto& interface = sensorInfo.propertyInterfaces.begin();
    msg.append(interface->first);
    for (const auto& property : interface->second)
    {
        msg.append(property.first);
        std::variant<T> value = static_cast<T>((cmdData.assertOffset8_14 << 8) |
                                               cmdData.assertOffset0_7);
        msg.append(value);
    }
    return updateToDbus(msg);
}

/** @brief Update d-bus based on a discrete reading
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return an IPMI error code
 */
template <typename T>
ipmi_ret_t readingData(const SetSensorReadingReq& cmdData,
                       const Info& sensorInfo)
{
    T raw_value =
        (sensorInfo.coefficientM * cmdData.reading) + sensorInfo.scaledOffset;

    raw_value *= std::pow(10, sensorInfo.exponentR - sensorInfo.scale);

    auto msg =
        makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
                    "Set", sensorInfo.sensorInterface);

    const auto& interface = sensorInfo.propertyInterfaces.begin();
    msg.append(interface->first);

    for (const auto& property : interface->second)
    {
        msg.append(property.first);
        std::variant<T> value = raw_value;
        msg.append(value);
    }
    return updateToDbus(msg);
}

/** @brief Update d-bus based on eventdata type sensor data
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo,
                     uint8_t data);

/** @brief Update d-bus based on eventdata1 type sensor data
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
inline ipmi_ret_t eventdata1(const SetSensorReadingReq& cmdData,
                             const Info& sensorInfo)
{
    return eventdata(cmdData, sensorInfo, cmdData.eventData1);
}

/** @brief Update d-bus based on eventdata2 type sensor data
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
inline ipmi_ret_t eventdata2(const SetSensorReadingReq& cmdData,
                             const Info& sensorInfo)
{
    return eventdata(cmdData, sensorInfo, cmdData.eventData2);
}

/** @brief Update d-bus based on eventdata3 type sensor data
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
inline ipmi_ret_t eventdata3(const SetSensorReadingReq& cmdData,
                             const Info& sensorInfo)
{
    return eventdata(cmdData, sensorInfo, cmdData.eventData3);
}

} // namespace set

namespace notify
{

/** @brief Make a DBus message for a Dbus call
 *  @param[in] updateInterface - Interface name
 *  @param[in] sensorPath - Path of the sensor
 *  @param[in] command - command to be executed
 *  @param[in] sensorInterface - DBus interface of sensor
 *  @return a dbus message
 */
IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
                           const std::string& sensorPath,
                           const std::string& command,
                           const std::string& sensorInterface);

/** @brief Update d-bus based on assertion type sensor data
 *  @param[in] interfaceMap - sensor interface
 *  @param[in] cmdData - input sensor data
 *  @param[in] sensorInfo - sensor d-bus info
 *  @return a IPMI error code
 */
ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
                     const Info& sensorInfo);

} // namespace notify

namespace inventory
{

namespace get
{

/**
 *  @brief Map the Dbus info to sensor's assertion status in the Get sensor
 *         reading command response.
 *
 *  @param[in] sensorInfo - Dbus info related to sensor.
 *
 *  @return Response for get sensor reading command.
 */
GetSensorResponse assertion(const Info& sensorInfo);

} // namespace get

} // namespace inventory
} // namespace sensor
} // namespace ipmi
