#include "rtnetlink_server.hpp"

#include "netlink.hpp"
#include "network_manager.hpp"
#include "rtnetlink.hpp"
#include "types.hpp"

#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <netinet/in.h>

#include <memory>
#include <phosphor-logging/log.hpp>
#include <stdplus/fd/create.hpp>
#include <stdplus/fd/ops.hpp>
#include <string_view>

namespace phosphor
{
namespace network
{

extern std::unique_ptr<Timer> refreshObjectTimer;

namespace netlink
{

using phosphor::logging::entry;
using phosphor::logging::level;
using phosphor::logging::log;

static bool shouldRefresh(const struct nlmsghdr& hdr,
                          std::string_view data) noexcept
{
    switch (hdr.nlmsg_type)
    {
        case RTM_NEWLINK:
        case RTM_DELLINK:
            return true;
        case RTM_NEWNEIGH:
        case RTM_DELNEIGH:
        {
            if (data.size() < sizeof(ndmsg))
            {
                return false;
            }
            const auto& ndm = *reinterpret_cast<const ndmsg*>(data.data());
            // We only want to refresh for static neighbors
            return ndm.ndm_state & NUD_PERMANENT;
        }
    }
    return false;
}

static void rthandler(Manager& m, bool n, std::string_view data)
{
    auto ret = netlink::gatewayFromRtm(data);
    if (!ret)
    {
        return;
    }
    auto ifIdx = std::get<unsigned>(*ret);
    auto it = m.interfacesByIdx.find(ifIdx);
    if (it == m.interfacesByIdx.end())
    {
        auto msg = fmt::format("Interface `{}` not found for route", ifIdx);
        log<level::ERR>(msg.c_str(), entry("IFIDX=%u", ifIdx));
        return;
    }
    std::visit(
        [&](auto addr) {
            if constexpr (std::is_same_v<in_addr, decltype(addr)>)
            {
                if (n)
                {
                    it->second->EthernetInterfaceIntf::defaultGateway(
                        std::to_string(addr));
                }
                else if (it->second->defaultGateway() == std::to_string(addr))
                {
                    it->second->EthernetInterfaceIntf::defaultGateway("");
                }
            }
            else if constexpr (std::is_same_v<in6_addr, decltype(addr)>)
            {
                if (n)
                {
                    it->second->EthernetInterfaceIntf::defaultGateway6(
                        std::to_string(addr));
                }
                else if (it->second->defaultGateway6() == std::to_string(addr))
                {
                    it->second->EthernetInterfaceIntf::defaultGateway6("");
                }
            }
            else
            {
                static_assert(!std::is_same_v<void, decltype(addr)>);
            }
        },
        std::get<InAddrAny>(*ret));
}

static void addrhandler(Manager& m, bool n, std::string_view data)
{
    auto info = netlink::addrFromRtm(data);
    auto it = m.interfacesByIdx.find(info.ifidx);
    if (it == m.interfacesByIdx.end())
    {
        auto msg = fmt::format("Interface `{}` not found for addr", info.ifidx);
        log<level::ERR>(msg.c_str(), entry("IFIDX=%u", info.ifidx));
        return;
    }
    if (n)
    {
        it->second->addAddr(info);
    }
    else
    {
        it->second->addrs.erase(info.ifaddr);
    }
}

static void handler(Manager& m, const nlmsghdr& hdr, std::string_view data)
{
    if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
    {
        refreshObjectTimer->restartOnce(refreshTimeout);
    }
    switch (hdr.nlmsg_type)
    {
        case RTM_NEWROUTE:
            rthandler(m, true, data);
            break;
        case RTM_DELROUTE:
            rthandler(m, false, data);
            break;
        case RTM_NEWADDR:
            addrhandler(m, true, data);
            break;
        case RTM_DELADDR:
            addrhandler(m, false, data);
            break;
    }
}

static void eventHandler(Manager& m, sdeventplus::source::IO&, int fd, uint32_t)
{
    auto cb = [&](auto&&... args) {
        return handler(m, std::forward<decltype(args)>(args)...);
    };
    while (receive(fd, cb) > 0)
        ;
}

static stdplus::ManagedFd makeSock()
{
    using namespace stdplus::fd;

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

    sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock));

    sockaddr_nl local{};
    local.nl_family = AF_NETLINK;
    local.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
                      RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
    bind(sock, local);

    return sock;
}

Server::Server(sdeventplus::Event& event, Manager& manager) :
    sock(makeSock()),
    io(event, sock.get(), EPOLLIN | EPOLLET, [&](auto&&... args) {
        return eventHandler(manager, std::forward<decltype(args)>(args)...);
    })
{
}

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