#include "mock_syscall.hpp"
#include "network_manager.hpp"
#include "rtnetlink_server.hpp"
#include "types.hpp"

#include <linux/rtnetlink.h>
#include <net/if.h>

#include <chrono>
#include <functional>
#include <sdbusplus/bus.hpp>
#include <sdeventplus/event.hpp>

#include <gtest/gtest.h>

namespace phosphor
{

namespace network
{
sdbusplus::bus::bus bus(sdbusplus::bus::new_default());
std::unique_ptr<Manager> manager = nullptr;
std::unique_ptr<Timer> refreshObjectTimer = nullptr;
std::unique_ptr<Timer> restartTimer = nullptr;
EventPtr eventPtr = nullptr;

/** @brief refresh the network objects. */
void refreshObjects()
{

    if (manager)
    {
        manager->createChildObjects();
    }
}

void initializeTimers()
{
    refreshObjectTimer = std::make_unique<Timer>(
        sdeventplus::Event::get_default(), std::bind(refreshObjects));
}

class TestRtNetlink : public testing::Test
{

  public:
    std::string confDir;
    phosphor::Descriptor smartSock;

    TestRtNetlink()
    {
        manager =
            std::make_unique<Manager>(bus, "/xyz/openbmc_test/bcd", "/tmp");
        sd_event* events;
        sd_event_default(&events);
        eventPtr.reset(events);
        events = nullptr;
        setConfDir();
        initializeTimers();
        createNetLinkSocket();
        bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
        rtnetlink::Server svr(eventPtr, smartSock);
    }

    ~TestRtNetlink()
    {
        if (confDir.empty())
        {
            fs::remove_all(confDir);
        }
    }

    void setConfDir()
    {
        char tmp[] = "/tmp/NetworkManager.XXXXXX";
        confDir = mkdtemp(tmp);
        manager->setConfDir(confDir);
    }

    bool isInterfaceAdded(std::string intf)
    {
        return manager->interfaces.find(intf) != manager->interfaces.end()
                   ? true
                   : false;
    }

    void createNetLinkSocket()
    {
        // RtnetLink socket
        auto fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
        smartSock.set(fd);
    }
};

TEST_F(TestRtNetlink, WithSingleInterface)
{
    using namespace std::chrono;
    // Adds the following ip in the getifaddrs list.
    mock_addIP("igb5", "127.0.0.1", "255.255.255.128", IFF_UP | IFF_RUNNING);
    constexpr auto BUFSIZE = 4096;
    std::array<char, BUFSIZE> msgBuf = {0};

    // point the header and the msg structure pointers into the buffer.
    auto nlMsg = reinterpret_cast<nlmsghdr*>(msgBuf.data());
    // Length of message
    nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
    nlMsg->nlmsg_type = RTM_GETADDR;
    nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
    nlMsg->nlmsg_seq = 0;
    nlMsg->nlmsg_pid = getpid();

    EXPECT_EQ(false, isInterfaceAdded("igb5"));
    // Send the request
    send(smartSock(), nlMsg, nlMsg->nlmsg_len, 0);

    int i = 3;
    while (i--)
    {
        // wait for timer to expire
        std::this_thread::sleep_for(std::chrono::milliseconds(refreshTimeout));
        sd_event_run(eventPtr.get(), 10);
    };

    EXPECT_EQ(true, isInterfaceAdded("igb5"));
}

} // namespace network
} // namespace phosphor
