#include "dbus_to_event_handler.hpp"

#include "libpldmresponder/pdr.hpp"

#include <phosphor-logging/lg2.hpp>

PHOSPHOR_LOG2_USING;

namespace pldm
{
using namespace pldm::responder;
using namespace pldm::responder::pdr;
using namespace pldm::responder::pdr_utils;
using namespace pldm::utils;
using namespace sdbusplus::bus::match::rules;

namespace state_sensor
{
const std::vector<uint8_t> pdrTypes{PLDM_STATE_SENSOR_PDR};

DbusToPLDMEvent::DbusToPLDMEvent(
    int /* mctp_fd */, uint8_t mctp_eid, pldm::InstanceIdDb& instanceIdDb,
    pldm::requester::Handler<pldm::requester::Request>* handler) :
    mctp_eid(mctp_eid), instanceIdDb(instanceIdDb), handler(handler)
{}

void DbusToPLDMEvent::sendEventMsg(uint8_t eventType,
                                   const std::vector<uint8_t>& eventDataVec)
{
    auto instanceId = instanceIdDb.next(mctp_eid);
    std::vector<uint8_t> requestMsg(
        sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
        eventDataVec.size());
    auto request = new (requestMsg.data()) pldm_msg;

    auto rc = encode_platform_event_message_req(
        instanceId, 1 /*formatVersion*/, TERMINUS_ID /*tId*/, eventType,
        eventDataVec.data(), eventDataVec.size(), request,
        eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
    if (rc != PLDM_SUCCESS)
    {
        instanceIdDb.free(mctp_eid, instanceId);
        error(
            "Failed to encode platform event message request, response code '{RC}'",
            "RC", rc);
        return;
    }

    auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
                                                  const pldm_msg* response,
                                                  size_t respMsgLen) {
        if (response == nullptr || !respMsgLen)
        {
            error("Failed to receive response for platform event message");
            return;
        }
        uint8_t completionCode{};
        uint8_t status{};
        auto rc = decode_platform_event_message_resp(response, respMsgLen,
                                                     &completionCode, &status);
        if (rc || completionCode)
        {
            error(
                "Failed to decode response of platform event message, response code '{RC}' and completion code '{CC}'",
                "RC", rc, "CC", completionCode);
        }
    };

    rc = handler->registerRequest(
        mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
        std::move(requestMsg), std::move(platformEventMessageResponseHandler));
    if (rc)
    {
        error("Failed to send the platform event message, response code '{RC}'",
              "RC", rc);
    }
}

void DbusToPLDMEvent::sendStateSensorEvent(SensorId sensorId,
                                           const DbusObjMaps& dbusMaps)
{
    // Encode PLDM platform event msg to indicate a state sensor change.
    // DSP0248_1.2.0 Table 19
    if (!dbusMaps.contains(sensorId))
    {
        // this is not an error condition, if we end up here
        // that means that the sensor with the sensor id has
        // custom behaviour(or probably an oem sensor) in
        // sending events that cannot be captured via standard
        // dbus-json infastructure
        return;
    }

    size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1;
    const auto& [dbusMappings, dbusValMaps] = dbusMaps.at(sensorId);
    for (size_t offset = 0; offset < dbusMappings.size(); ++offset)
    {
        std::vector<uint8_t> sensorEventDataVec{};
        sensorEventDataVec.resize(sensorEventSize);
        auto eventData = new (sensorEventDataVec.data()) pldm_sensor_event_data;
        eventData->sensor_id = sensorId;
        eventData->sensor_event_class_type = PLDM_STATE_SENSOR_STATE;
        eventData->event_class[0] = static_cast<uint8_t>(offset);
        eventData->event_class[1] = PLDM_SENSOR_UNKNOWN;
        eventData->event_class[2] = PLDM_SENSOR_UNKNOWN;

        const auto& dbusMapping = dbusMappings[offset];
        const auto& dbusValueMapping = dbusValMaps[offset];
        auto stateSensorMatch = std::make_unique<sdbusplus::bus::match_t>(
            pldm::utils::DBusHandler::getBus(),
            propertiesChanged(dbusMapping.objectPath.c_str(),
                              dbusMapping.interface.c_str()),
            [this, sensorEventDataVec, dbusValueMapping, dbusMapping, sensorId,
             offset](auto& msg) mutable {
                DbusChangedProps props{};
                std::string intf;
                uint8_t previousState = PLDM_SENSOR_UNKNOWN;
                msg.read(intf, props);
                if (!props.contains(dbusMapping.propertyName))
                {
                    return;
                }
                for (const auto& itr : dbusValueMapping)
                {
                    bool findValue = false;
                    if (dbusMapping.propertyType == "string")
                    {
                        std::string src = std::get<std::string>(itr.second);
                        std::string dst = std::get<std::string>(
                            props.at(dbusMapping.propertyName));

                        auto values = pldm::utils::split(src, "||", " ");
                        for (const auto& value : values)
                        {
                            if (value == dst)
                            {
                                findValue = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        findValue =
                            itr.second == props.at(dbusMapping.propertyName)
                                ? true
                                : false;
                    }

                    if (findValue)
                    {
                        auto eventData = new (sensorEventDataVec.data())
                            pldm_sensor_event_data;
                        eventData->event_class[1] = itr.first;
                        if (sensorCacheMap.contains(sensorId) &&
                            sensorCacheMap[sensorId][offset] !=
                                PLDM_SENSOR_UNKNOWN)
                        {
                            previousState = sensorCacheMap[sensorId][offset];
                        }
                        else
                        {
                            previousState = itr.first;
                        }
                        eventData->event_class[2] = previousState;
                        this->sendEventMsg(PLDM_SENSOR_EVENT,
                                           sensorEventDataVec);
                        updateSensorCacheMaps(sensorId, offset, previousState);
                        break;
                    }
                }
            });
        stateSensorMatchs.emplace_back(std::move(stateSensorMatch));
    }
}

void DbusToPLDMEvent::listenSensorEvent(const pdr_utils::Repo& repo,
                                        const DbusObjMaps& dbusMaps)
{
    const std::map<Type, sensorEvent> sensorHandlers = {
        {PLDM_STATE_SENSOR_PDR,
         [this](SensorId sensorId, const DbusObjMaps& dbusMaps) {
             this->sendStateSensorEvent(sensorId, dbusMaps);
         }}};

    pldm_state_sensor_pdr* pdr = nullptr;
    std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> sensorPdrRepo(
        pldm_pdr_init(), pldm_pdr_destroy);
    if (!sensorPdrRepo)
    {
        throw std::runtime_error("Unable to instantiate sensor PDR repository");
    }

    for (auto pdrType : pdrTypes)
    {
        Repo sensorPDRs(sensorPdrRepo.get());
        getRepoByType(repo, sensorPDRs, pdrType);
        if (sensorPDRs.empty())
        {
            return;
        }

        PdrEntry pdrEntry{};
        auto pdrRecord = sensorPDRs.getFirstRecord(pdrEntry);
        while (pdrRecord)
        {
            pdr = new (pdrEntry.data) pldm_state_sensor_pdr;
            SensorId sensorId = LE16TOH(pdr->sensor_id);
            if (sensorHandlers.contains(pdrType))
            {
                sensorHandlers.at(pdrType)(sensorId, dbusMaps);
            }

            pdrRecord = sensorPDRs.getNextRecord(pdrRecord, pdrEntry);
        }
    }
}

} // namespace state_sensor
} // namespace pldm
