#include "common/transport.hpp"

#include <libpldm/transport.h>
#include <libpldm/transport/af-mctp.h>
#include <libpldm/transport/mctp-demux.h>

#include <algorithm>
#include <ranges>
#include <system_error>

struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd);
void transport_impl_destroy(TransportImpl& impl);

static constexpr uint8_t MCTP_EID_VALID_MIN = 8;
static constexpr uint8_t MCTP_EID_VALID_MAX = 255;

/*
 * Currently the OpenBMC ecosystem assumes TID == EID. Pre-populate the TID
 * mappings over the EID space excluding the Null (0), Reserved (1 to 7),
 * Broadcast EIDs (255) defined by Section 8.2 Special endpoint IDs in DSP0236
 * v1.3.1. Further, by Section 8.1.1 SetTID command (0x01) in DSP0240 v1.1.0,
 * the TIDs 0x00 and 0xff are also reserved. These overlap with the reserved
 * EIDs so no additional filtering is required.
 *
 * Further, pldmtool and pldmd are two separate processes. They are opening two
 * different sockets, but with the mctp-demux-daemon, the response messages are
 * broadcasted to all sockets. When pldmd receives the response for a request
 * issued by pldmtool, pldm_transport_mctp_demux_recv() may return with error
 * PLDM_REQUESTER_RECV_FAIL if it fails to map the EID of the source endpoint to
 * its TID. The EID to TID mappings of pldmtool and pldmd should be coherent to
 * prevent the failure of pldm_transport_mctp_demux_recv().
 */

[[maybe_unused]] static struct pldm_transport*
    pldm_transport_impl_mctp_demux_init(TransportImpl& impl, pollfd& pollfd)
{
    impl.mctp_demux = nullptr;
    pldm_transport_mctp_demux_init(&impl.mctp_demux);
    if (!impl.mctp_demux)
    {
        return nullptr;
    }

    for (const auto eid :
         std::views::iota(MCTP_EID_VALID_MIN, MCTP_EID_VALID_MAX))
    {
        int rc = pldm_transport_mctp_demux_map_tid(impl.mctp_demux, eid, eid);
        if (rc)
        {
            pldm_transport_af_mctp_destroy(impl.af_mctp);
            return nullptr;
        }
    }

    pldm_transport* pldmTransport =
        pldm_transport_mctp_demux_core(impl.mctp_demux);

    if (pldmTransport != nullptr)
    {
        pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd);
    }

    return pldmTransport;
}

[[maybe_unused]] static struct pldm_transport* pldm_transport_impl_af_mctp_init(
    TransportImpl& impl, pollfd& pollfd)
{
    impl.af_mctp = nullptr;
    pldm_transport_af_mctp_init(&impl.af_mctp);
    if (!impl.af_mctp)
    {
        return nullptr;
    }

    for (const auto eid :
         std::views::iota(MCTP_EID_VALID_MIN, MCTP_EID_VALID_MAX))
    {
        int rc = pldm_transport_af_mctp_map_tid(impl.af_mctp, eid, eid);
        if (rc)
        {
            pldm_transport_af_mctp_destroy(impl.af_mctp);
            return nullptr;
        }
    }

    /* Listen for requests on any interface */
    if (pldm_transport_af_mctp_bind(impl.af_mctp, nullptr, 0))
    {
        return nullptr;
    }

    pldm_transport* pldmTransport = pldm_transport_af_mctp_core(impl.af_mctp);

    if (pldmTransport != nullptr)
    {
        pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd);
    }

    return pldmTransport;
}

struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd)
{
#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
    return pldm_transport_impl_mctp_demux_init(impl, pollfd);
#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
    return pldm_transport_impl_af_mctp_init(impl, pollfd);
#else
    return nullptr;
#endif
}

void transport_impl_destroy(TransportImpl& impl)
{
#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
    pldm_transport_mctp_demux_destroy(impl.mctp_demux);
#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
    pldm_transport_af_mctp_destroy(impl.af_mctp);
#endif
}

PldmTransport::PldmTransport()
{
    transport = transport_impl_init(impl, pfd);
    if (!transport)
    {
        throw std::system_error(ENOMEM, std::generic_category());
    }
}

PldmTransport::~PldmTransport()
{
    transport_impl_destroy(impl);
}

int PldmTransport::getEventSource() const
{
    return pfd.fd;
}

pldm_requester_rc_t PldmTransport::sendMsg(pldm_tid_t tid, const void* tx,
                                           size_t len)
{
    return pldm_transport_send_msg(transport, tid, tx, len);
}

pldm_requester_rc_t PldmTransport::recvMsg(pldm_tid_t& tid, void*& rx,
                                           size_t& len)
{
    return pldm_transport_recv_msg(transport, &tid, (void**)&rx, &len);
}

pldm_requester_rc_t PldmTransport::sendRecvMsg(
    pldm_tid_t tid, const void* tx, size_t txLen, void*& rx, size_t& rxLen)
{
    return pldm_transport_send_recv_msg(transport, tid, tx, txLen, &rx, &rxLen);
}
