#include "pldm.hpp"

#include "file.hpp"

#include <fmt/core.h>
#include <libpldm/entity.h>
#include <libpldm/platform.h>
#include <libpldm/state_set.h>
#include <libpldm/state_set_oem_ibm.h>

#include <phosphor-logging/log.hpp>

namespace pldm
{

using namespace phosphor::logging;

void Interface::fetchSensorInfo(uint16_t stateSetId,
                                SensorToInstance& sensorInstanceMap,
                                SensorOffset& sensorOffset)
{
    PdrList pdrs{};

    auto& bus = open_power::occ::utils::getBus();
    try
    {
        auto method = bus.new_method_call(
            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
            "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
        method.append(tid, (uint16_t)PLDM_ENTITY_PROC, stateSetId);

        auto responseMsg = bus.call(method);
        responseMsg.read(pdrs);
    }
    catch (const sdbusplus::exception::exception& e)
    {
        log<level::ERR>("pldm: Failed to fetch the state sensor PDRs",
                        entry("ERROR=%s", e.what()));
    }

    if (pdrs.empty())
    {
        log<level::ERR>("pldm: state sensor PDRs not present");
        return;
    }

    bool offsetFound = false;
    auto stateSensorPDR =
        reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
    auto possibleStatesPtr = stateSensorPDR->possible_states;
    for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
         offset++)
    {
        auto possibleStates =
            reinterpret_cast<const state_sensor_possible_states*>(
                possibleStatesPtr);

        if (possibleStates->state_set_id == stateSetId)
        {
            sensorOffset = offset;
            offsetFound = true;
            break;
        }
        possibleStatesPtr += sizeof(possibleStates->state_set_id) +
                             sizeof(possibleStates->possible_states_size) +
                             possibleStates->possible_states_size;
    }

    if (!offsetFound)
    {
        log<level::ERR>("pldm: state sensor PDR not found");
        return;
    }

    // To order SensorID based on the EntityInstance.
    // Note that when a proc is on a DCM, the PDRs for these sensors
    // could have the same instance IDs but different container IDs.
    std::map<uint32_t, SensorID> entityInstMap{};
    for (auto& pdr : pdrs)
    {
        auto pdrPtr =
            reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
        uint32_t key = (static_cast<uint32_t>(pdrPtr->container_id) << 16) |
                       static_cast<uint32_t>(pdrPtr->entity_instance);
        entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
    }

    open_power::occ::instanceID count = start;
    for (auto const& pair : entityInstMap)
    {
        sensorInstanceMap.emplace(pair.second, count);
        count++;
    }
}

void Interface::sensorEvent(sdbusplus::message::message& msg)
{
    if (!isOCCSensorCacheValid())
    {
        fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
                        sensorToOCCInstance, OCCSensorOffset);
    }

    if (sensorToSBEInstance.empty())
    {
        fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
                        SBESensorOffset);
    }

    TerminusID tid{};
    SensorID sensorId{};
    SensorOffset msgSensorOffset{};
    EventState eventState{};
    EventState previousEventState{};

    msg.read(tid, sensorId, msgSensorOffset, eventState, previousEventState);

    if (msgSensorOffset == OCCSensorOffset)
    {
        auto sensorEntry = sensorToOCCInstance.find(sensorId);

        if (sensorEntry != sensorToOCCInstance.end())
        {
            if (eventState ==
                static_cast<EventState>(
                    PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
            {
                log<level::INFO>(
                    fmt::format("PLDM: OCC{} is RUNNING", sensorEntry->second)
                        .c_str());
                callBack(sensorEntry->second, true);
            }
            else if (eventState ==
                     static_cast<EventState>(
                         PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
            {
                log<level::INFO>(fmt::format("PLDM: OCC{} has now STOPPED",
                                             sensorEntry->second)
                                     .c_str());
                callBack(sensorEntry->second, false);
            }

            return;
        }
    }

    if (msgSensorOffset == SBESensorOffset)
    {
        auto sensorEntry = sensorToSBEInstance.find(sensorId);

        if (sensorEntry != sensorToSBEInstance.end())
        {
            if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
            {
                log<level::INFO>("pldm: HRESET is NOT READY",
                                 entry("SBE=%d", sensorEntry->second));
            }
            else if (eventState == static_cast<EventState>(SBE_HRESET_READY))
            {
                sbeCallBack(sensorEntry->second, true);
            }
            else if (eventState == static_cast<EventState>(SBE_HRESET_FAILED))
            {
                sbeCallBack(sensorEntry->second, false);
            }
        }
    }
}

void Interface::hostStateEvent(sdbusplus::message::message& msg)
{
    std::map<std::string, std::variant<std::string>> properties{};
    std::string interface;
    msg.read(interface, properties);
    const auto stateEntry = properties.find("CurrentHostState");
    if (stateEntry != properties.end())
    {
        auto stateEntryValue = stateEntry->second;
        auto propVal = std::get<std::string>(stateEntryValue);
        if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
        {
            sensorToOCCInstance.clear();
            occInstanceToEffecter.clear();

            sensorToSBEInstance.clear();
            sbeInstanceToEffecter.clear();
        }
    }
}

void Interface::fetchEffecterInfo(uint16_t stateSetId,
                                  InstanceToEffecter& instanceToEffecterMap,
                                  CompositeEffecterCount& effecterCount,
                                  uint8_t& stateIdPos)
{
    PdrList pdrs{};

    auto& bus = open_power::occ::utils::getBus();
    try
    {
        auto method = bus.new_method_call(
            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
            "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
        method.append(tid, (uint16_t)PLDM_ENTITY_PROC, stateSetId);

        auto responseMsg = bus.call(method);
        responseMsg.read(pdrs);
    }
    catch (const sdbusplus::exception::exception& e)
    {
        log<level::ERR>("pldm: Failed to fetch the state effecter PDRs",
                        entry("ERROR=%s", e.what()));
    }

    if (!pdrs.size())
    {
        log<level::ERR>("pldm: state effecter PDRs not present");
        return;
    }

    bool offsetFound = false;
    auto stateEffecterPDR =
        reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
    auto possibleStatesPtr = stateEffecterPDR->possible_states;
    for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
         offset++)
    {
        auto possibleStates =
            reinterpret_cast<const state_effecter_possible_states*>(
                possibleStatesPtr);

        if (possibleStates->state_set_id == stateSetId)
        {
            stateIdPos = offset;
            effecterCount = stateEffecterPDR->composite_effecter_count;
            offsetFound = true;
            break;
        }
        possibleStatesPtr += sizeof(possibleStates->state_set_id) +
                             sizeof(possibleStates->possible_states_size) +
                             possibleStates->possible_states_size;
    }

    if (!offsetFound)
    {
        return;
    }

    std::map<uint32_t, EffecterID> entityInstMap{};
    for (auto& pdr : pdrs)
    {
        auto pdrPtr =
            reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
        uint32_t key = (static_cast<uint32_t>(pdrPtr->container_id) << 16) |
                       static_cast<uint32_t>(pdrPtr->entity_instance);
        entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
    }

    open_power::occ::instanceID position = start;
    for (auto const& pair : entityInstMap)
    {
        instanceToEffecterMap.emplace(position, pair.second);
        position++;
    }
}

std::vector<uint8_t>
    Interface::prepareSetEffecterReq(uint8_t instanceId, EffecterID effecterId,
                                     CompositeEffecterCount effecterCount,
                                     uint8_t stateIdPos, uint8_t stateSetValue)
{
    std::vector<uint8_t> request(
        sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
        (effecterCount * sizeof(set_effecter_state_field)));
    auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
    std::vector<set_effecter_state_field> stateField;

    for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
    {
        if (effecterPos == stateIdPos)
        {
            stateField.emplace_back(
                set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
        }
        else
        {
            stateField.emplace_back(
                set_effecter_state_field{PLDM_NO_CHANGE, 0});
        }
    }
    auto rc = encode_set_state_effecter_states_req(
        instanceId, effecterId, effecterCount, stateField.data(), requestMsg);
    if (rc != PLDM_SUCCESS)
    {
        log<level::ERR>("encode set effecter states request returned error ",
                        entry("RC=%d", rc));
        request.clear();
    }
    return request;
}

void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
{
    if (!isPDREffecterCacheValid())
    {
        fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
                          occInstanceToEffecter, OCCEffecterCount,
                          bootRestartPosition);
    }

    // Find the matching effecter for the OCC instance
    auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
    if (effecterEntry == occInstanceToEffecter.end())
    {
        log<level::ERR>(
            fmt::format(
                "pldm: Failed to find a matching effecter for OCC instance {}",
                occInstanceId)
                .c_str());

        return;
    }

    uint8_t instanceId{};
    if (!getMctpInstanceId(instanceId))
    {
        return;
    }

    // Prepare the SetStateEffecterStates request to reset the OCC
    auto request = prepareSetEffecterReq(
        instanceId, effecterEntry->second, OCCEffecterCount,
        bootRestartPosition, PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);

    if (request.empty())
    {
        log<level::ERR>("pldm: SetStateEffecterStates OCC reset request empty");
        return;
    }

    // Make asynchronous call to reset the OCCs/PM Complex
    sendPldm(request, true);
}

void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
{
    if (sbeInstanceToEffecter.empty())
    {
        fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
                          sbeInstanceToEffecter, SBEEffecterCount,
                          sbeMaintenanceStatePosition);
    }

    auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
    if (effecterEntry == sbeInstanceToEffecter.end())
    {
        log<level::ERR>(
            "pldm: Failed to find a matching effecter for SBE instance",
            entry("SBE=%d", sbeInstanceId));
        return;
    }

    uint8_t instanceId{};
    if (!getMctpInstanceId(instanceId))
    {
        return;
    }

    // Prepare the SetStateEffecterStates request to HRESET the SBE
    auto request = prepareSetEffecterReq(
        instanceId, effecterEntry->second, SBEEffecterCount,
        sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);

    if (request.empty())
    {
        log<level::ERR>("pldm: SetStateEffecterStates HRESET request empty");
        return;
    }

    // Make asynchronous call to do the reset
    sendPldm(request, true);
}

bool Interface::getMctpInstanceId(uint8_t& instanceId)
{
    auto& bus = open_power::occ::utils::getBus();
    try
    {
        auto method = bus.new_method_call(
            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
            "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
        method.append(mctpEid);
        auto reply = bus.call(method);
        reply.read(instanceId);
    }
    catch (const sdbusplus::exception::exception& e)
    {
        log<level::ERR>("pldm: GetInstanceId returned error",
                        entry("ERROR=%s", e.what()));
        return false;
    }

    return true;
}

void Interface::sendPldm(const std::vector<uint8_t>& request, const bool async)
{
    // Connect to MCTP scoket
    int fd = pldm_open();
    if (fd == -1)
    {
        log<level::ERR>(
            fmt::format("sendPldm: Failed to connect to MCTP socket, errno={}",
                        errno)
                .c_str());
        return;
    }

    open_power::occ::FileDescriptor fileFd(fd);

    // Send the PLDM request message to HBRT
    if (async == false)
    {
        uint8_t* response = nullptr;
        size_t responseSize{};
        auto rc = pldm_send_recv(mctpEid, fileFd(), request.data(),
                                 request.size(), &response, &responseSize);
        std::unique_ptr<uint8_t, decltype(std::free)*> responsePtr{response,
                                                                   std::free};
        if (rc)
        {
            log<level::ERR>(
                fmt::format(
                    "sendPldm: pldm_send_recv({},{},req,{},...) failed with rc={} and errno={}",
                    mctpEid, fileFd(), request.size(), rc, errno)
                    .c_str());
        }

        uint8_t completionCode{};
        auto responseMsg = reinterpret_cast<const pldm_msg*>(responsePtr.get());
        auto rcDecode = decode_set_state_effecter_states_resp(
            responseMsg, responseSize - sizeof(pldm_msg_hdr), &completionCode);
        if (rcDecode || completionCode)
        {
            log<level::ERR>(
                fmt::format(
                    "sendPldm: decode_set_state_effecter_states_resp failed with rc={} and compCode={}",
                    rcDecode, completionCode)
                    .c_str());
        }
    }
    else
    {
        log<level::INFO>(fmt::format("sendPldm: calling pldm_send({}, {})",
                                     mctpEid, fileFd())
                             .c_str());
        auto rc = pldm_send(mctpEid, fileFd(), request.data(), request.size());
        if (rc)
        {
            log<level::ERR>(
                fmt::format(
                    "sendPldm: pldm_send({},{},req,{}) failed with rc={} and errno={}",
                    mctpEid, fileFd(), request.size(), rc, errno)
                    .c_str());
        }
    }
}

} // namespace pldm
