/*
 * SPDX-FileCopyrightText: Copyright OpenBMC Authors
 * SPDX-License-Identifier: Apache-2.0
 */

#include "NvidiaPcieFunction.hpp"

#include "Utils.hpp"

#include <MctpRequester.hpp>
#include <NvidiaGpuMctpVdm.hpp>
#include <NvidiaUtils.hpp>
#include <OcpMctpVdm.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/message/native_types.hpp>

#include <cstddef>
#include <cstdint>
#include <format>
#include <memory>
#include <span>
#include <string>
#include <system_error>
#include <tuple>
#include <vector>

using Association = std::tuple<std::string, std::string, std::string>;

NvidiaPcieFunction::NvidiaPcieFunction(
    std::shared_ptr<sdbusplus::asio::connection>& conn,
    mctp::MctpRequester& mctpRequester, const std::string& pcieDeviceName,
    const std::string& path, uint8_t eid, uint8_t functionNumber,
    sdbusplus::asio::object_server& objectServer,
    gpu::DeviceIdentification deviceType) :
    eid(eid), path(path), conn(conn), mctpRequester(mctpRequester),
    objectServer(objectServer), deviceType(deviceType)
{
    int rc = 0;
    switch (deviceType)
    {
        case gpu::DeviceIdentification::DEVICE_GPU:
            request.resize(gpu::queryScalarGroupTelemetryV1RequestSize);
            rc = gpu::encodeQueryScalarGroupTelemetryV1Request(
                0, 0, gpu::PcieScalarGroupId::PciIdentity, request);
            break;
        case gpu::DeviceIdentification::DEVICE_PCIE:
            request.resize(gpu::queryScalarGroupTelemetryV2RequestSize);
            rc = gpu::encodeQueryScalarGroupTelemetryV2Request(
                0, {}, 0, 0, gpu::PcieScalarGroupId::PciIdentity, request);
            break;
        default:
            break;
    }
    if (rc != 0)
    {
        request.clear();
        lg2::error("Failed to encode PCIe Function request: rc={RC}, EID={EID}",
                   "RC", rc, "EID", eid);
    }

    const sdbusplus::object_path dbusPath =
        inventoryPrefix / pcieDeviceName /
        std::format("Function{}", functionNumber);

    pcieFunctionInterface = objectServer.add_interface(
        dbusPath, "xyz.openbmc_project.Inventory.Item.PCIeFunction");

    pcieFunctionInterface->register_property("FunctionNumber", functionNumber);
    pcieFunctionInterface->register_property("VendorId",
                                             static_cast<uint16_t>(0));
    pcieFunctionInterface->register_property("DeviceId",
                                             static_cast<uint16_t>(0));
    pcieFunctionInterface->register_property("SubsystemVendorId",
                                             static_cast<uint16_t>(0));
    pcieFunctionInterface->register_property("SubsystemId",
                                             static_cast<uint16_t>(0));
    if (deviceType == gpu::DeviceIdentification::DEVICE_GPU)
    {
        pcieFunctionInterface->register_property(
            "DeviceClass",
            std::string("xyz.openbmc_project.Inventory.Item.PCIeFunction"
                        ".DeviceClasses.ProcessingAccelerators"));
        pcieFunctionInterface->register_property(
            "FunctionType",
            std::string("xyz.openbmc_project.Inventory.Item.PCIeFunction"
                        ".FunctionTypes.Physical"));
    }

    if (!pcieFunctionInterface->initialize())
    {
        lg2::error("Error initializing PCIe Function interface, eid={EID}",
                   "EID", eid);
    }

    const sdbusplus::object_path pcieDevicePath =
        inventoryPrefix / pcieDeviceName;

    std::vector<Association> associations;
    associations.emplace_back("exposed_by", "exposing", pcieDevicePath);

    associationInterface =
        objectServer.add_interface(dbusPath, association::interface);
    associationInterface->register_property("Associations", associations);

    if (!associationInterface->initialize())
    {
        lg2::error(
            "Error initializing Association interface for PCIe Function, eid={EID}",
            "EID", eid);
    }
}

NvidiaPcieFunction::~NvidiaPcieFunction()
{
    objectServer.remove_interface(pcieFunctionInterface);
    objectServer.remove_interface(associationInterface);
}

void NvidiaPcieFunction::processResponse(const std::error_code& ec,
                                         std::span<const uint8_t> response)
{
    if (ec)
    {
        lg2::error(
            "Error updating PCIe Function: sending message over MCTP failed, "
            "rc={RC}, EID={EID}",
            "RC", ec.value(), "EID", eid);
        return;
    }

    ocp::accelerator_management::CompletionCode cc{};
    uint16_t reasonCode = 0;
    size_t numTelemetryValue = 0;

    int rc = 0;
    switch (deviceType)
    {
        case gpu::DeviceIdentification::DEVICE_GPU:
            rc = gpu::decodeQueryScalarGroupTelemetryV1Response(
                response, cc, reasonCode, numTelemetryValue, telemetryValues);
            break;
        case gpu::DeviceIdentification::DEVICE_PCIE:
            rc = gpu::decodeQueryScalarGroupTelemetryV2Response(
                response, cc, reasonCode, numTelemetryValue, telemetryValues);
            break;
        default:
            return;
    }

    if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error("Error updating PCIe Function: decode failed, "
                   "rc={RC}, cc={CC}, reasonCode={RESC}, EID={EID}",
                   "RC", rc, "CC", static_cast<uint8_t>(cc), "RESC", reasonCode,
                   "EID", eid);
        return;
    }

    if (numTelemetryValue < 4)
    {
        lg2::error(
            "Error updating PCIe Function: insufficient telemetry values, "
            "NumValues={NUM}, EID={EID}",
            "NUM", numTelemetryValue, "EID", eid);
        return;
    }

    pcieFunctionInterface->set_property(
        "VendorId", static_cast<uint16_t>(telemetryValues[0]));
    pcieFunctionInterface->set_property(
        "DeviceId", static_cast<uint16_t>(telemetryValues[1]));
    pcieFunctionInterface->set_property(
        "SubsystemVendorId", static_cast<uint16_t>(telemetryValues[2]));
    pcieFunctionInterface->set_property(
        "SubsystemId", static_cast<uint16_t>(telemetryValues[3]));
}

void NvidiaPcieFunction::update()
{
    if (request.empty())
    {
        return;
    }

    mctpRequester.sendRecvMsg(
        eid, request,
        [weak{weak_from_this()}](const std::error_code& ec,
                                 std::span<const uint8_t> buffer) {
            std::shared_ptr<NvidiaPcieFunction> self = weak.lock();
            if (!self)
            {
                lg2::error("Invalid reference to NvidiaPcieFunction");
                return;
            }
            self->processResponse(ec, buffer);
        });
}
