#pragma once

#include "config.h"

#include "libpldmresponder/pdr.hpp"
#include "libpldmresponder/utils.hpp"

#include <stdint.h>

#include <map>

#include "libpldm/platform.h"
#include "libpldm/states.h"

namespace pldm
{

using Response = std::vector<uint8_t>;

namespace responder
{

namespace platform
{

/** @brief Register handlers for commands from the platform spec
 */
void registerHandlers();

} // namespace platform

/** @brief Handler for GetPDR
 *
 *  @param[in] request - Request message payload
 *  @param[in] payloadLength - Request payload length
 *  @param[out] Response - Response message written here
 */
Response getPDR(const pldm_msg* request, size_t payloadLength);

/** @brief Handler for setStateEffecterStates
 *
 *  @param[in] request - Request message
 *  @param[in] payloadLength - Request payload length
 *  @return Response - PLDM Response message
 */
Response setStateEffecterStates(const pldm_msg* request, size_t payloadLength);

/** @brief Function to set the effecter requested by pldm requester
 *  @param[in] dBusIntf - The interface object
 *  @param[in] effecterId - Effecter ID sent by the requester to act on
 *  @param[in] stateField - The state field data for each of the states, equal
 *        to composite effecter count in number
 *  @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>
int setStateEffecterStatesHandler(
    const DBusInterface& dBusIntf, effecter::Id effecterId,
    const std::vector<set_effecter_state_field>& stateField)
{
    using namespace std::string_literals;
    using DBusProperty = std::variant<std::string, bool>;
    using StateSetId = uint16_t;
    using StateSetNum = uint8_t;
    using PropertyMap =
        std::map<StateSetId, std::map<StateSetNum, DBusProperty>>;
    static const PropertyMap stateNumToDbusProp = {
        {PLDM_BOOT_PROGRESS_STATE,
         {{PLDM_BOOT_NOT_ACTIVE,
           "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
           "Standby"s},
          {PLDM_BOOT_COMPLETED,
           "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
           "BootComplete"s}}},
    };
    using namespace phosphor::logging;
    using namespace pldm::responder::pdr;
    using namespace pldm::responder::effecter::dbus_mapping;

    state_effecter_possible_states* states = nullptr;
    pldm_state_effecter_pdr* pdr = nullptr;
    uint8_t compEffecterCnt = stateField.size();
    uint32_t recordHndl{};
    Repo& pdrRepo = get(PDR_JSONS_DIR);
    pdr::Entry pdrEntry{};

    while (!pdr)
    {
        pdrEntry = pdrRepo.at(recordHndl);
        pldm_pdr_hdr* header = reinterpret_cast<pldm_pdr_hdr*>(pdrEntry.data());
        if (header->type != PLDM_STATE_EFFECTER_PDR)
        {
            recordHndl = pdrRepo.getNextRecordHandle(recordHndl);
            if (recordHndl)
            {
                continue;
            }
            return PLDM_PLATFORM_INVALID_EFFECTER_ID;
        }
        pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data());
        recordHndl = pdr->hdr.record_handle;
        if (pdr->effecter_id == effecterId)
        {
            states = reinterpret_cast<state_effecter_possible_states*>(
                pdr->possible_states);
            if (compEffecterCnt > pdr->composite_effecter_count)
            {
                log<level::ERR>("The requester sent wrong composite effecter "
                                "count for the effecter",
                                entry("EFFECTER_ID=%d", effecterId),
                                entry("COMP_EFF_CNT=%d", compEffecterCnt));
                return PLDM_ERROR_INVALID_DATA;
            }
            break;
        }
        recordHndl = pdrRepo.getNextRecordHandle(recordHndl);
        if (!recordHndl)
        {
            return PLDM_PLATFORM_INVALID_EFFECTER_ID;
        }
        pdr = nullptr;
    }

    std::map<StateSetId, std::function<int(const std::string& objPath,
                                           const uint8_t currState)>>
        effecterToDbusEntries = {
            {PLDM_BOOT_PROGRESS_STATE,
             [&](const std::string& objPath, const uint8_t currState) {
                 auto stateSet =
                     stateNumToDbusProp.find(PLDM_BOOT_PROGRESS_STATE);
                 if (stateSet == stateNumToDbusProp.end())
                 {
                     log<level::ERR>("Couldn't find D-Bus mapping for "
                                     "PLDM_BOOT_PROGRESS_STATE",
                                     entry("EFFECTER_ID=%d", effecterId));
                     return PLDM_ERROR;
                 }
                 auto iter = stateSet->second.find(
                     stateField[currState].effecter_state);
                 if (iter == stateSet->second.end())
                 {
                     log<level::ERR>(
                         "Invalid state field passed or field not "
                         "found for PLDM_BOOT_PROGRESS_STATE",
                         entry("EFFECTER_ID=%d", effecterId),
                         entry("FIELD=%d",
                               stateField[currState].effecter_state),
                         entry("OBJECT_PATH=%s", objPath.c_str()));
                     return PLDM_ERROR_INVALID_DATA;
                 }
                 auto dbusProp = "OperatingSystemState";
                 std::variant<std::string> value{
                     std::get<std::string>(iter->second)};
                 auto dbusInterface =
                     "xyz.openbmc_project.State.OperatingSystem.Status";
                 try
                 {
                     dBusIntf.setDbusProperty(objPath.c_str(), dbusProp,
                                              dbusInterface, value);
                 }
                 catch (const std::exception& e)
                 {
                     log<level::ERR>("Error setting property",
                                     entry("ERROR=%s", e.what()),
                                     entry("PROPERTY=%s", dbusProp),
                                     entry("INTERFACE=%s", dbusInterface),
                                     entry("PATH=%s", objPath.c_str()));
                     return PLDM_ERROR;
                 }
                 return PLDM_SUCCESS;
             }}};

    int rc = PLDM_SUCCESS;
    auto paths = get(effecterId);
    for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
    {
        std::vector<StateSetNum> allowed{};
        // computation is based on table 79 from DSP0248 v1.1.1
        uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
        uint8_t bit =
            stateField[currState].effecter_state - (8 * bitfieldIndex);
        if (states->possible_states_size < bitfieldIndex ||
            !(states->states[bitfieldIndex].byte & (1 << bit)))
        {
            log<level::ERR>(
                "Invalid state set value", entry("EFFECTER_ID=%d", effecterId),
                entry("VALUE=%d", stateField[currState].effecter_state),
                entry("COMPOSITE_EFFECTER_ID=%d", currState),
                entry("DBUS_PATH=%c", paths[currState].c_str()));
            rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
            break;
        }
        auto iter = effecterToDbusEntries.find(states->state_set_id);
        if (iter == effecterToDbusEntries.end())
        {
            uint16_t setId = states->state_set_id;
            log<level::ERR>(
                "Did not find the state set for the state effecter pdr  ",
                entry("STATE=%d", setId), entry("EFFECTER_ID=%d", effecterId));
            rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
            break;
        }
        if (stateField[currState].set_request == PLDM_REQUEST_SET)
        {
            rc = iter->second(paths[currState], currState);
            if (rc != PLDM_SUCCESS)
            {
                break;
            }
        }
        uint8_t* nextState =
            reinterpret_cast<uint8_t*>(states) +
            sizeof(state_effecter_possible_states) - sizeof(states->states) +
            (states->possible_states_size * sizeof(states->states));
        states = reinterpret_cast<state_effecter_possible_states*>(nextState);
    }
    return rc;
}

} // namespace responder
} // namespace pldm
