#include "net_iface_mock.h"
#include "nic_mock.h"
#include "platforms/nemora/portable/default_addresses.h"
#include "platforms/nemora/portable/ncsi.h"
#include "platforms/nemora/portable/ncsi_fsm.h"
#include "platforms/nemora/portable/net_types.h"

#include <ncsi_state_machine.h>
#include <net_config.h>
#include <net_sockio.h>
#include <netinet/ether.h>
#include <netinet/in.h>

#include <gmock/gmock.h>

namespace
{

constexpr uint32_t ETHER_NCSI = 0x88f8;

class MockConfig : public net::ConfigBase
{
  public:
    int get_mac_addr(mac_addr_t* mac) override
    {
        std::memcpy(mac, &mac_addr, sizeof(mac_addr_t));

        return 0;
    }

    int set_mac_addr(const mac_addr_t& mac) override
    {
        mac_addr = mac;

        return 0;
    }

    int set_nic_hostless(bool is_hostless) override
    {
        is_nic_hostless = is_hostless;

        return 0;
    }

    mac_addr_t mac_addr;
    bool is_nic_hostless = true;
};

class NICConnection : public net::SockIO
{
  public:
    int write(const void* buf, size_t len) override
    {
        conseq_reads = 0;
        ++n_writes;
        std::memcpy(last_write.data, buf, len);
        last_write.len = len;
        const auto* hdr = reinterpret_cast<const struct ether_header*>(buf);
        if (ETHER_NCSI == ntohs(hdr->ether_type))
        {
            ++n_handles;
            next_read.len = nic_mock.handle_request(last_write, &next_read);
        }

        return len;
    }

    int recv(void* buf, size_t maxlen) override
    {
        ++n_reads;
        ++conseq_reads;

        if (read_timeout > 0)
        {
            if (conseq_reads > read_timeout)
            {
                return 0;
            }
        }

        if (maxlen < next_read.len)
        {
            ++n_read_errs;
            return 0;
        }

        std::memcpy(buf, next_read.data, next_read.len);

        return next_read.len;
    }

    mock::NIC nic_mock{false, 2};
    int n_writes = 0;
    int n_reads = 0;
    int n_handles = 0;
    int n_read_errs = 0;

    // Max number of consequitive reads without writes.
    int read_timeout = -1;
    int conseq_reads = 0;

    ncsi_buf_t last_write = {};
    ncsi_buf_t next_read = {};
};

} // namespace

class TestNcsi : public testing::Test
{
  public:
    void SetUp() override
    {
        ncsi_sm.set_sockio(&ncsi_sock);
        ncsi_sm.set_net_config(&net_config_mock);
        ncsi_sm.set_retest_delay(0);
        ncsi_sock.nic_mock.set_mac(nic_mac);
        ncsi_sock.nic_mock.set_hostless(true);
        ncsi_sock.read_timeout = 10;
    }

  protected:
    void ExpectFiltersNotConfigured()
    {
        for (uint8_t i = 0; i < ncsi_sock.nic_mock.get_channel_count(); ++i)
        {
            EXPECT_FALSE(ncsi_sock.nic_mock.is_filter_configured(i));
        }
    }

    void ExpectFiltersConfigured()
    {
        // Check that filters are configured on all channels.
        for (uint8_t i = 0; i < ncsi_sock.nic_mock.get_channel_count(); ++i)
        {
            EXPECT_TRUE(ncsi_sock.nic_mock.is_filter_configured(i));
            const ncsi_oem_filter_t& ch_filter =
                ncsi_sock.nic_mock.get_filter(i);

            for (unsigned i = 0; i < sizeof(nic_mac.octet); ++i)
            {
                EXPECT_EQ(nic_mac.octet[i], ch_filter.mac[i]);
            }

            EXPECT_EQ(ch_filter.ip, 0);
            const uint16_t filter_port = ntohs(ch_filter.port);
            EXPECT_EQ(filter_port, DEFAULT_ADDRESSES_RX_PORT);
        }
    }

    MockConfig net_config_mock;
    NICConnection ncsi_sock;
    ncsi::StateMachine ncsi_sm;
    const mac_addr_t nic_mac = {{0xde, 0xca, 0xfb, 0xad, 0x01, 0x02}};

    // Number of states in each state machine
    static constexpr int l2_num_states = 26;
    static constexpr int l3l4_num_states = 2;
    static constexpr int test_num_states = 9;

    // Total number of states in all three state machines.
    static constexpr int total_num_states =
        l2_num_states + l3l4_num_states + test_num_states;
};

TEST_F(TestNcsi, TestMACAddrPropagation)
{
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);
    EXPECT_EQ(0, std::memcmp(nic_mac.octet, net_config_mock.mac_addr.octet,
                             sizeof(nic_mac.octet)));

    // Since network is not configured, the filters should not be configured
    // either.
    ExpectFiltersNotConfigured();
}

TEST_F(TestNcsi, TestFilterConfiguration)
{
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);

    ExpectFiltersConfigured();
}

TEST_F(TestNcsi, TestFilterReset)
{
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);

    // Since network is not configured, the filters should not be configured
    // either.
    ExpectFiltersNotConfigured();

    ncsi_sm.run(total_num_states);

    ExpectFiltersConfigured();
}

TEST_F(TestNcsi, TestRetest)
{
    ncsi_sm.run(total_num_states + test_num_states);

    // Verify that the test state machine was stepped through twice,
    // by counting how many times the last command of the state machine
    // has been executed.
    const uint8_t last_test_command = NCSI_GET_LINK_STATUS;
    const auto& cmd_log = ncsi_sock.nic_mock.get_command_log();
    int num_test_runs = 0;
    for (const auto& ncsi_frame : cmd_log)
    {
        if (ncsi_frame.get_control_packet_type() == last_test_command)
        {
            ++num_test_runs;
        }
    }

    EXPECT_EQ(num_test_runs, 2);
}

TEST_F(TestNcsi, TestHostlessSwitch)
{
    // By default the NIC is in hostless mode.
    // Verify that net config flag changes after FSM run.
    net_config_mock.is_nic_hostless = false;
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);
    EXPECT_TRUE(net_config_mock.is_nic_hostless);

    // Now disable the hostless mode and verify that net config
    // flag changes to false.
    ncsi_sock.nic_mock.set_hostless(false);
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);
    EXPECT_FALSE(net_config_mock.is_nic_hostless);
}
