#pragma once

#include "common/utils.hpp"
#include "libpldmresponder/pdr.hpp"
#include "pdr_utils.hpp"
#include "pldmd/handler.hpp"

#include <libpldm/platform.h>
#include <libpldm/states.h>
#include <math.h>
#include <stdint.h>

#include <phosphor-logging/lg2.hpp>

#include <map>
#include <optional>

PHOSPHOR_LOG2_USING;

namespace pldm
{
namespace responder
{
namespace platform_numeric_effecter
{
/** @brief Function to get the effecter value by PDR factor coefficient, etc.
 *  @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
 *  @param[in] effecterValue - effecter value.
 *  @param[in] propertyType - type of the D-Bus property.
 *
 *  @return - std::pair<int, std::optional<PropertyValue>> - rc:Success or
 *          failure, PropertyValue: The value to be set
 */
template <typename T>
std::pair<int, std::optional<pldm::utils::PropertyValue>>
    getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr,
                        T& effecterValue, std::string propertyType)
{
    // X = Round [ (Y - B) / m ]
    // refer to DSP0248_1.2.0 27.8
    int rc = 0;
    pldm::utils::PropertyValue value;
    switch (pdr->effecter_data_size)
    {
        case PLDM_EFFECTER_DATA_SIZE_UINT8:
        {
            auto rawValue = static_cast<uint8_t>(
                round(effecterValue - pdr->offset) / pdr->resolution);
            if (pdr->min_settable.value_u8 < pdr->max_settable.value_u8 &&
                (rawValue < pdr->min_settable.value_u8 ||
                 rawValue > pdr->max_settable.value_u8))
            {
                rc = PLDM_ERROR_INVALID_DATA;
            }
            value = rawValue;
            if (propertyType == "uint64_t")
            {
                auto tempValue = std::get<uint8_t>(value);
                value = static_cast<uint64_t>(tempValue);
            }
            else if (propertyType == "uint32_t")
            {
                auto tempValue = std::get<uint8_t>(value);
                value = static_cast<uint32_t>(tempValue);
            }
            break;
        }
        case PLDM_EFFECTER_DATA_SIZE_SINT8:
        {
            auto rawValue = static_cast<int8_t>(
                round(effecterValue - pdr->offset) / pdr->resolution);
            if (pdr->min_settable.value_s8 < pdr->max_settable.value_s8 &&
                (rawValue < pdr->min_settable.value_s8 ||
                 rawValue > pdr->max_settable.value_s8))
            {
                rc = PLDM_ERROR_INVALID_DATA;
            }
            value = rawValue;
            break;
        }
        case PLDM_EFFECTER_DATA_SIZE_UINT16:
        {
            auto rawValue = static_cast<uint16_t>(
                round(effecterValue - pdr->offset) / pdr->resolution);
            if (pdr->min_settable.value_u16 < pdr->max_settable.value_u16 &&
                (rawValue < pdr->min_settable.value_u16 ||
                 rawValue > pdr->max_settable.value_u16))
            {
                rc = PLDM_ERROR_INVALID_DATA;
            }
            value = rawValue;
            if (propertyType == "uint64_t")
            {
                auto tempValue = std::get<uint16_t>(value);
                value = static_cast<uint64_t>(tempValue);
            }
            else if (propertyType == "uint32_t")
            {
                auto tempValue = std::get<uint16_t>(value);
                value = static_cast<uint32_t>(tempValue);
            }
            break;
        }
        case PLDM_EFFECTER_DATA_SIZE_SINT16:
        {
            auto rawValue = static_cast<int16_t>(
                round(effecterValue - pdr->offset) / pdr->resolution);
            if (pdr->min_settable.value_s16 < pdr->max_settable.value_s16 &&
                (rawValue < pdr->min_settable.value_s16 ||
                 rawValue > pdr->max_settable.value_s16))
            {
                rc = PLDM_ERROR_INVALID_DATA;
            }
            value = rawValue;
            if (propertyType == "uint64_t")
            {
                auto tempValue = std::get<int16_t>(value);
                value = static_cast<uint64_t>(tempValue);
            }
            else if (propertyType == "uint32_t")
            {
                auto tempValue = std::get<int16_t>(value);
                value = static_cast<uint32_t>(tempValue);
            }
            break;
        }
        case PLDM_EFFECTER_DATA_SIZE_UINT32:
        {
            auto rawValue = static_cast<uint32_t>(
                round(effecterValue - pdr->offset) / pdr->resolution);
            if (pdr->min_settable.value_u32 < pdr->max_settable.value_u32 &&
                (rawValue < pdr->min_settable.value_u32 ||
                 rawValue > pdr->max_settable.value_u32))
            {
                rc = PLDM_ERROR_INVALID_DATA;
            }
            value = rawValue;
            if (propertyType == "uint64_t")
            {
                auto tempValue = std::get<uint32_t>(value);
                value = static_cast<uint64_t>(tempValue);
            }
            else if (propertyType == "uint32_t")
            {
                auto tempValue = std::get<uint32_t>(value);
                value = static_cast<uint32_t>(tempValue);
            }
            break;
        }
        case PLDM_EFFECTER_DATA_SIZE_SINT32:
        {
            auto rawValue = static_cast<int32_t>(
                round(effecterValue - pdr->offset) / pdr->resolution);
            if (pdr->min_settable.value_s32 < pdr->max_settable.value_s32 &&
                (rawValue < pdr->min_settable.value_s32 ||
                 rawValue > pdr->max_settable.value_s32))
            {
                rc = PLDM_ERROR_INVALID_DATA;
            }
            value = rawValue;
            if (propertyType == "uint64_t")
            {
                auto tempValue = std::get<int32_t>(value);
                value = static_cast<uint64_t>(tempValue);
            }
            else if (propertyType == "uint32_t")
            {
                auto tempValue = std::get<int32_t>(value);
                value = static_cast<uint32_t>(tempValue);
            }
            break;
        }
    }

    return {rc, std::make_optional(std::move(value))};
}

/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
 *  @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
 *  @param[in] effecterDataSize - effecter value size.
 *  @param[in,out] effecterValue - effecter value.
 *  @param[in] propertyType - type of the D-Bus property.
 *
 *  @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
 *          failure, PropertyValue: The value to be set
 */
std::pair<int, std::optional<pldm::utils::PropertyValue>>
    convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
                       uint8_t effecterDataSize, uint8_t* effecterValue,
                       std::string propertyType)
{
    if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
    {
        uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
        return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
    }
    else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
    {
        int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
        return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
    }
    else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
    {
        uint16_t currentValue =
            *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
        return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
    }
    else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
    {
        int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
        return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
    }
    else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
    {
        uint32_t currentValue =
            *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
        return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
    }
    else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
    {
        int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
        return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
    }
    else
    {
        error("Wrong field effecterDataSize...");
        return {PLDM_ERROR, {}};
    }
}

/** @brief Function to set the effecter value requested by pldm requester
 *  @tparam[in] DBusInterface - DBus interface type
 *  @tparam[in] Handler - pldm::responder::platform::Handler
 *  @param[in] dBusIntf - The interface object of DBusInterface
 *  @param[in] handler - The interface object of
 *             pldm::responder::platform::Handler
 *  @param[in] effecterId - Effecter ID sent by the requester to act on
 *  @param[in] effecterDataSize - The bit width and format of the setting
 * 				value for the effecter
 *  @param[in] effecter_value - The setting value of numeric effecter being
 * 				requested.
 *  @param[in] effecterValueLength - The setting value length of numeric
 *              effecter being requested.
 *  @return - Success or failure in setting the states. Returns failure in
 * terms of PLDM completion codes if atleast one state fails to be set
 */
template <class DBusInterface, class Handler>
int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
                                   Handler& handler, uint16_t effecterId,
                                   uint8_t effecterDataSize,
                                   uint8_t* effecterValue,
                                   size_t effecterValueLength)
{
    constexpr auto effecterValueArrayLength = 4;
    pldm_numeric_effecter_value_pdr* pdr = nullptr;

    std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
        numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
    pldm::responder::pdr_utils::Repo numericEffecterPDRs(
        numericEffecterPdrRepo.get());
    pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs,
                                        PLDM_NUMERIC_EFFECTER_PDR);
    if (numericEffecterPDRs.empty())
    {
        error("The Numeric Effecter PDR repo is empty.");
        return PLDM_ERROR;
    }

    // Get the pdr structure of pldm_numeric_effecter_value_pdr according
    // to the effecterId
    pldm::responder::pdr_utils::PdrEntry pdrEntry{};
    auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
    while (pdrRecord)
    {
        pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
        if (pdr->effecter_id != effecterId)
        {
            pdr = nullptr;
            pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
            continue;
        }

        break;
    }

    if (!pdr)
    {
        return PLDM_PLATFORM_INVALID_EFFECTER_ID;
    }

    if (effecterValueLength != effecterValueArrayLength)
    {
        error("effecter data size is incorrect.");
        return PLDM_ERROR_INVALID_DATA;
    }

    try
    {
        const auto& [dbusMappings,
                     dbusValMaps] = handler.getDbusObjMaps(effecterId);
        pldm::utils::DBusMapping dbusMapping{
            dbusMappings[0].objectPath, dbusMappings[0].interface,
            dbusMappings[0].propertyName, dbusMappings[0].propertyType};

        // convert to dbus effectervalue according to the factor
        auto [rc, dbusValue] = convertToDbusValue(
            pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
        if (rc != PLDM_SUCCESS)
        {
            return rc;
        }
        try
        {
            dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
        }
        catch (const std::exception& e)
        {
            error(
                "Error setting property, ERROR={ERR_EXCEP} PROPERTY={DBUS_PROP} INTERFACE={DBUS_INTF} PATH={DBUS_OBJ_PATH}",
                "ERR_EXCEP", e.what(), "DBUS_PROP", dbusMapping.propertyName,
                "DBUS_INTF", dbusMapping.interface, "DBUS_OBJ_PATH",
                dbusMapping.objectPath.c_str());
            return PLDM_ERROR;
        }
    }
    catch (const std::out_of_range& e)
    {
        error("Unknown effecter ID : {EFFECTER_ID} {ERR_EXCEP}", "EFFECTER_ID",
              effecterId, "ERR_EXCEP", e.what());
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

} // namespace platform_numeric_effecter
} // namespace responder
} // namespace pldm
