#include "netlink.hpp"

#include <fmt/format.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#include <array>
#include <stdexcept>
#include <stdplus/fd/create.hpp>
#include <stdplus/fd/ops.hpp>
#include <stdplus/raw.hpp>
#include <system_error>

using stdplus::raw::Aligned;

namespace phosphor
{
namespace network
{
namespace netlink
{
namespace detail
{

void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb)
{
    // Parse and update the message buffer
    const auto& hdr = stdplus::raw::refFrom<nlmsghdr, Aligned>(msgs);
    if (hdr.nlmsg_len < sizeof(hdr))
    {
        throw std::runtime_error(
            fmt::format("nlmsg length shorter than header: {} < {}",
                        hdr.nlmsg_len, sizeof(hdr)));
    }
    if (msgs.size() < hdr.nlmsg_len)
    {
        throw std::runtime_error(
            fmt::format("not enough message for nlmsg: {} < {}", msgs.size(),
                        hdr.nlmsg_len));
    }
    auto msg = msgs.substr(NLMSG_HDRLEN, hdr.nlmsg_len - NLMSG_HDRLEN);
    msgs.remove_prefix(NLMSG_ALIGN(hdr.nlmsg_len));

    // Figure out how to handle the individual message
    bool doCallback = true;
    if (hdr.nlmsg_flags & NLM_F_MULTI)
    {
        done = false;
    }
    if (hdr.nlmsg_type == NLMSG_NOOP)
    {
        doCallback = false;
    }
    else if (hdr.nlmsg_type == NLMSG_DONE)
    {
        if (done)
        {
            throw std::runtime_error("Got done for non-multi msg");
        }
        done = true;
        doCallback = false;
    }
    else if (hdr.nlmsg_type == NLMSG_ERROR)
    {
        const auto& err = stdplus::raw::refFrom<nlmsgerr, Aligned>(msg);
        // This is just an ACK so don't do the callback
        if (err.error <= 0)
        {
            doCallback = false;
        }
    }
    // All multi-msg headers must have the multi flag
    if (!done && !(hdr.nlmsg_flags & NLM_F_MULTI))
    {
        throw std::runtime_error("Got non-multi msg before done");
    }
    if (doCallback)
    {
        cb(hdr, msg);
    }
}

static void requestSend(int sock, void* data, size_t size)
{
    sockaddr_nl dst{};
    dst.nl_family = AF_NETLINK;

    iovec iov{};
    iov.iov_base = data;
    iov.iov_len = size;

    msghdr hdr{};
    hdr.msg_name = reinterpret_cast<sockaddr*>(&dst);
    hdr.msg_namelen = sizeof(dst);
    hdr.msg_iov = &iov;
    hdr.msg_iovlen = 1;

    if (sendmsg(sock, &hdr, 0) < 0)
    {
        throw std::system_error(errno, std::generic_category(),
                                "netlink sendmsg");
    }
}

static stdplus::ManagedFd makeSocket(int protocol)
{
    using namespace stdplus::fd;

    auto sock = socket(SocketDomain::Netlink, SocketType::Raw,
                       static_cast<stdplus::fd::SocketProto>(protocol));

    sockaddr_nl local{};
    local.nl_family = AF_NETLINK;
    bind(sock, local);

    return sock;
}

void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb)
{
    auto sock = makeSocket(protocol);
    requestSend(sock.get(), data, size);
    receive(sock.get(), cb);
}

} // namespace detail

size_t receive(int sock, ReceiveCallback cb)
{
    // We need to make sure we have enough room for an entire packet otherwise
    // it gets truncated. The netlink docs guarantee packets will not exceed 8K
    std::array<char, 8192> buf;

    iovec iov{};
    iov.iov_base = buf.data();
    iov.iov_len = buf.size();

    sockaddr_nl from{};
    from.nl_family = AF_NETLINK;

    msghdr hdr{};
    hdr.msg_name = &from;
    hdr.msg_namelen = sizeof(from);
    hdr.msg_iov = &iov;
    hdr.msg_iovlen = 1;

    // We only do multiple recvs if we have a MULTI type message
    bool done = true;
    size_t num_msgs = 0;
    do
    {
        ssize_t recvd = recvmsg(sock, &hdr, 0);
        if (recvd < 0 && errno != EAGAIN)
        {
            throw std::system_error(errno, std::generic_category(),
                                    "netlink recvmsg");
        }
        if (recvd <= 0)
        {
            if (!done)
            {
                throw std::runtime_error("netlink recvmsg: Got empty payload");
            }
            return num_msgs;
        }

        std::string_view msgs(buf.data(), recvd);
        do
        {
            detail::processMsg(msgs, done, cb);
            num_msgs++;
        } while (!done && !msgs.empty());

        if (done && !msgs.empty())
        {
            throw std::runtime_error("Extra unprocessed netlink messages");
        }
    } while (!done);
    return num_msgs;
}

std::tuple<rtattr, std::string_view> extractRtAttr(std::string_view& data)
{
    const auto& hdr = stdplus::raw::refFrom<rtattr, Aligned>(data);
    if (hdr.rta_len < RTA_LENGTH(0))
    {
        throw std::runtime_error(fmt::format(
            "rtattr shorter than header: {} < {}", hdr.rta_len, RTA_LENGTH(0)));
    }
    if (data.size() < hdr.rta_len)
    {
        throw std::runtime_error(
            fmt::format("not enough message for rtattr: {} < {}", data.size(),
                        hdr.rta_len));
    }
    auto attr = data.substr(RTA_LENGTH(0), hdr.rta_len - RTA_LENGTH(0));
    data.remove_prefix(RTA_ALIGN(hdr.rta_len));
    return {hdr, attr};
}

} // namespace netlink
} // namespace network
} // namespace phosphor
