#include "network/switch/unicast_table.h"

namespace dofs {

std::vector<PortId> UnicastTable::get_port_list(NodeId dst_node,
                PortId dst_port) const {
        const IPv4Addr k = ipv4(dst_node, dst_port);
        auto it = _table.find(k);

        if (it == _table.end())
                return {};

        return it->second;
}

bool UnicastTable::add_entry(NodeId dst_node, PortId dst_port,
                             PortId out_port) {
        const IPv4Addr k = ipv4(dst_node, dst_port);
        auto& vec = _table[k];
        return insert_sorted_unique(vec, out_port);
}

bool UnicastTable::delete_entry(NodeId dst_node, PortId dst_port,
                                PortId out_port) {
        const IPv4Addr k = ipv4(dst_node, dst_port);
        auto it = _table.find(k);

        if (it == _table.end())
                return false;

        return erase_sorted(it->second, out_port);
}

bool UnicastTable::insert_sorted_unique(std::vector<PortId> &vec, PortId v) {
        auto it = std::lower_bound(vec.begin(), vec.end(), v);

        if (it != vec.end() && *it == v)
                return false;

        vec.insert(it, v);
        return true;
}

bool UnicastTable::erase_sorted(std::vector<PortId> &vec, PortId v) {
        auto it = std::lower_bound(vec.begin(), vec.end(), v);

        if (it == vec.end() || *it != v)
                return false;

        vec.erase(it);
        return true;
}

} // namespace dofs
