
#include "host_lamp_test.hpp"

#include "common/types.hpp"
#include "common/utils.hpp"

#include <libpldm/entity.h>
#include <libpldm/platform.h>
#include <libpldm/state_set.h>

PHOSPHOR_LOG2_USING;

namespace pldm
{
namespace led
{

bool HostLampTest::asserted() const
{
    return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted();
}

bool HostLampTest::asserted(bool value)
{
    // When setting the asserted property to true, need to notify the PHYP to
    // start lamp test.
    // When setting the asserted property to true again, need to notify the PHYP
    // and PHYP will restart the lamp test.
    // When setting the asserted property to false, just update the asserted
    // property, do not need to notify the PHYP to stop lamp test, PHYP will
    // wait for timeout to stop.
    if (!value &&
        value ==
            sdbusplus::xyz::openbmc_project::Led::server::Group::asserted())
    {
        return value;
    }

    if (value)
    {
        if (effecterID == 0)
        {
            effecterID = getEffecterID();
        }

        if (effecterID != 0)
        {
            // Call setHostStateEffecter method to notify PHYP to start lamp
            // test. If user set Asserted to true again, need to notify PHYP to
            // start lamptest again.
            uint8_t rc = setHostStateEffecter(effecterID);
            if (rc)
            {
                throw sdbusplus::exception::SdBusError(
                    static_cast<int>(std::errc::invalid_argument),
                    "Set Host State Effector to start lamp test failed");
            }
            else
            {
                return sdbusplus::xyz::openbmc_project::Led::server::Group::
                    asserted(value);
            }
        }
        else
        {
            throw sdbusplus::exception::SdBusError(
                static_cast<int>(std::errc::invalid_argument),
                "Get Effecter ID failed, effecter = 0");
        }
    }

    return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted(value);
}

uint16_t HostLampTest::getEffecterID()
{
    uint16_t effecterID = 0;

    if (!pdrRepo)
    {
        return effecterID;
    }

    // INDICATOR is a logical entity, so the bit 15 in entity type is set.
    pdr::EntityType entityType = PLDM_ENTITY_INDICATOR | 0x8000;

    auto stateEffecterPDRs = pldm::utils::findStateEffecterPDR(
        mctp_eid, entityType,
        static_cast<uint16_t>(PLDM_STATE_SET_IDENTIFY_STATE), pdrRepo);

    if (stateEffecterPDRs.empty())
    {
        error(
            "Lamp Test: The state set PDR can not be found, entityType = {ENTITY_TYP}",
            "ENTITY_TYP", entityType);
        return effecterID;
    }

    for (const auto& rep : stateEffecterPDRs)
    {
        auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(rep.data());
        effecterID = pdr->effecter_id;
        break;
    }

    return effecterID;
}

uint8_t HostLampTest::setHostStateEffecter(uint16_t effecterID)
{
    constexpr uint8_t effecterCount = 1;
    auto instanceIdResult = instanceIdDb.next(mctp_eid);
    if (!instanceIdResult)
    {
        return PLDM_ERROR;
    }
    auto instanceId = instanceIdResult.value();

    std::vector<uint8_t> requestMsg(
        sizeof(pldm_msg_hdr) + sizeof(effecterID) + sizeof(effecterCount) +
        sizeof(set_effecter_state_field));
    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
    set_effecter_state_field stateField{PLDM_REQUEST_SET,
                                        PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED};
    auto rc = encode_set_state_effecter_states_req(
        instanceId, effecterID, effecterCount, &stateField, request);
    if (rc != PLDM_SUCCESS)
    {
        instanceIdDb.free(mctp_eid, instanceId);
        error("Failed to encode_set_state_effecter_states_req, rc = {RC}", "RC",
              static_cast<int>(rc));
        return rc;
    }

    auto setStateEffecterStatesResponseHandler = [](mctp_eid_t /*eid*/,
                                                    const pldm_msg* response,
                                                    size_t respMsgLen) {
        if (!response || !respMsgLen)
        {
            error(
                "Failed to receive response for the Set State Effecter States");
            return;
        }

        uint8_t completionCode{};
        auto rc = decode_set_state_effecter_states_resp(response, respMsgLen,
                                                        &completionCode);

        if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
        {
            error(
                "Failed to decode_set_state_effecter_states_resp: rc={RC}, cc={CC}",
                "RC", rc, "CC", static_cast<unsigned>(completionCode));
        }
    };

    rc = handler->registerRequest(
        mctp_eid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES,
        std::move(requestMsg),
        std::move(setStateEffecterStatesResponseHandler));
    if (rc != PLDM_SUCCESS)
    {
        error("Failed to send the the Set State Effecter States request");
    }

    return rc;
}

} // namespace led
} // namespace pldm
