/*
 *  Copyright (c) 2018, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#include "router_table.hpp"

#if OPENTHREAD_FTD

#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/timer.hpp"
#include "thread/mle.hpp"
#include "thread/mle_router.hpp"
#include "thread/network_data_leader.hpp"
#include "thread/thread_netif.hpp"

namespace ot {

RegisterLogModule("RouterTable");

RouterTable::RouterTable(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mRouters(aInstance)
    , mChangedTask(aInstance)
    , mRouterIdSequenceLastUpdated(0)
    , mRouterIdSequence(Random::NonCrypto::GetUint8())
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
    , mMinRouterId(0)
    , mMaxRouterId(Mle::kMaxRouterId)
#endif
{
    Clear();
}

void RouterTable::Clear(void)
{
    ClearNeighbors();
    mRouterIdMap.Clear();
    mRouters.Clear();
    SignalTableChanged();
}

bool RouterTable::IsRouteTlvIdSequenceMoreRecent(const Mle::RouteTlv &aRouteTlv) const
{
    return (GetActiveRouterCount() == 0) ||
           SerialNumber::IsGreater(aRouteTlv.GetRouterIdSequence(), GetRouterIdSequence());
}

void RouterTable::ClearNeighbors(void)
{
    for (Router &router : mRouters)
    {
        if (router.IsStateValid())
        {
            Get<NeighborTable>().Signal(NeighborTable::kRouterRemoved, router);
            SignalTableChanged();
        }

        router.SetState(Neighbor::kStateInvalid);
    }
}

Router *RouterTable::AddRouter(uint8_t aRouterId)
{
    // Add a new `Router` entry to `mRouters` array with given
    // `aRouterId` and update the `mRouterIdMap`.

    Router *router = mRouters.PushBack();

    VerifyOrExit(router != nullptr);

    router->Clear();
    router->SetRloc16(Mle::Rloc16FromRouterId(aRouterId));
    router->SetNextHopToInvalid();

    mRouterIdMap.SetIndex(aRouterId, mRouters.IndexOf(*router));
    SignalTableChanged();

exit:
    return router;
}

void RouterTable::RemoveRouter(Router &aRouter)
{
    // Remove an existing `aRouter` entry from `mRouters` and update the
    // `mRouterIdMap`.

    if (aRouter.IsStateValid())
    {
        Get<NeighborTable>().Signal(NeighborTable::kRouterRemoved, aRouter);
    }

    mRouterIdMap.Release(aRouter.GetRouterId());
    mRouters.Remove(aRouter);

    // Removing `aRouter` from `mRouters` array will replace it with
    // the last entry in the array (if not already the last entry) so
    // we update the index in `mRouteIdMap` for the moved entry.

    if (IsAllocated(aRouter.GetRouterId()))
    {
        mRouterIdMap.SetIndex(aRouter.GetRouterId(), mRouters.IndexOf((aRouter)));
    }

    SignalTableChanged();
}

Router *RouterTable::Allocate(void)
{
    Router *router           = nullptr;
    uint8_t numAvailable     = 0;
    uint8_t selectedRouterId = Mle::kInvalidRouterId;

    VerifyOrExit(!mRouters.IsFull());

#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
    for (uint8_t routerId = mMinRouterId; routerId <= mMaxRouterId; routerId++)
#else
    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
#endif
    {
        if (mRouterIdMap.CanAllocate(routerId))
        {
            numAvailable++;

            // Randomly select a router ID as we iterate through the
            // list using Reservoir algorithm: We replace the
            // selected ID with current entry in the list with
            // probably `1/numAvailable`.

            if (Random::NonCrypto::GetUint8InRange(0, numAvailable) == 0)
            {
                selectedRouterId = routerId;
            }
        }
    }

    VerifyOrExit(selectedRouterId != Mle::kInvalidRouterId);

    router = Allocate(selectedRouterId);
    OT_ASSERT(router != nullptr);

exit:
    return router;
}

Router *RouterTable::Allocate(uint8_t aRouterId)
{
    Router *router = nullptr;

    VerifyOrExit(aRouterId <= Mle::kMaxRouterId && mRouterIdMap.CanAllocate(aRouterId));

    router = AddRouter(aRouterId);
    VerifyOrExit(router != nullptr);

    router->SetLastHeard(TimerMilli::GetNow());

    mRouterIdSequence++;
    mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
    Get<Mle::MleRouter>().ResetAdvertiseInterval();

    LogNote("Allocate router id %d", aRouterId);

exit:
    return router;
}

Error RouterTable::Release(uint8_t aRouterId)
{
    Error   error = kErrorNone;
    Router *router;

    OT_ASSERT(aRouterId <= Mle::kMaxRouterId);

    VerifyOrExit(Get<Mle::MleRouter>().IsLeader(), error = kErrorInvalidState);

    router = FindRouterById(aRouterId);
    VerifyOrExit(router != nullptr, error = kErrorNotFound);

    RemoveRouter(*router);

    for (Router &otherRouter : mRouters)
    {
        if (otherRouter.GetNextHop() == aRouterId)
        {
            otherRouter.SetNextHopToInvalid();
        }
    }

    mRouterIdSequence++;
    mRouterIdSequenceLastUpdated = TimerMilli::GetNow();

    Get<AddressResolver>().RemoveEntriesForRouterId(aRouterId);
    Get<NetworkData::Leader>().RemoveBorderRouter(Mle::Rloc16FromRouterId(aRouterId),
                                                  NetworkData::Leader::kMatchModeRouterId);
    Get<Mle::MleRouter>().ResetAdvertiseInterval();

    LogNote("Release router id %d", aRouterId);

exit:
    return error;
}

void RouterTable::RemoveRouterLink(Router &aRouter)
{
    if (aRouter.GetLinkQualityOut() != kLinkQuality0)
    {
        aRouter.SetLinkQualityOut(kLinkQuality0);
        aRouter.SetLastHeard(TimerMilli::GetNow());
        SignalTableChanged();
    }

    for (Router &router : mRouters)
    {
        if (router.GetNextHop() == aRouter.GetRouterId())
        {
            router.SetNextHopToInvalid();
            SignalTableChanged();

            if (GetLinkCost(router) >= Mle::kMaxRouteCost)
            {
                Get<Mle::MleRouter>().ResetAdvertiseInterval();
            }
        }
    }

    if (aRouter.GetNextHop() == Mle::kInvalidRouterId)
    {
        Get<Mle::MleRouter>().ResetAdvertiseInterval();

        // Clear all EID-to-RLOC entries associated with the router.
        Get<AddressResolver>().RemoveEntriesForRouterId(aRouter.GetRouterId());
    }
}

const Router *RouterTable::FindRouter(const Router::AddressMatcher &aMatcher) const
{
    return mRouters.FindMatching(aMatcher);
}

Router *RouterTable::FindNeighbor(uint16_t aRloc16)
{
    Router *router = nullptr;

    VerifyOrExit(aRloc16 != Get<Mle::MleRouter>().GetRloc16());
    router = FindRouter(Router::AddressMatcher(aRloc16, Router::kInStateValid));

exit:
    return router;
}

Router *RouterTable::FindNeighbor(const Mac::ExtAddress &aExtAddress)
{
    return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateValid));
}

Router *RouterTable::FindNeighbor(const Mac::Address &aMacAddress)
{
    return FindRouter(Router::AddressMatcher(aMacAddress, Router::kInStateValid));
}

const Router *RouterTable::FindRouterById(uint8_t aRouterId) const
{
    const Router *router = nullptr;

    VerifyOrExit(aRouterId <= Mle::kMaxRouterId);

    VerifyOrExit(IsAllocated(aRouterId));
    router = &mRouters[mRouterIdMap.GetIndex(aRouterId)];

exit:
    return router;
}

const Router *RouterTable::FindRouterByRloc16(uint16_t aRloc16) const
{
    return FindRouterById(Mle::RouterIdFromRloc16(aRloc16));
}

const Router *RouterTable::FindNextHopOf(const Router &aRouter) const { return FindRouterById(aRouter.GetNextHop()); }

Router *RouterTable::FindRouter(const Mac::ExtAddress &aExtAddress)
{
    return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateAny));
}

Error RouterTable::GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo)
{
    Error   error = kErrorNone;
    Router *router;
    uint8_t routerId;

    if (aRouterId <= Mle::kMaxRouterId)
    {
        routerId = static_cast<uint8_t>(aRouterId);
    }
    else
    {
        VerifyOrExit(Mle::IsActiveRouter(aRouterId), error = kErrorInvalidArgs);
        routerId = Mle::RouterIdFromRloc16(aRouterId);
        VerifyOrExit(routerId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
    }

    router = FindRouterById(routerId);
    VerifyOrExit(router != nullptr, error = kErrorNotFound);

    aRouterInfo.SetFrom(*router);

exit:
    return error;
}

const Router *RouterTable::GetLeader(void) const { return FindRouterById(Get<Mle::MleRouter>().GetLeaderId()); }

uint32_t RouterTable::GetLeaderAge(void) const
{
    return (!mRouters.IsEmpty()) ? Time::MsecToSec(TimerMilli::GetNow() - mRouterIdSequenceLastUpdated) : 0xffffffff;
}

uint8_t RouterTable::GetNeighborCount(LinkQuality aLinkQuality) const
{
    uint8_t count = 0;

    for (const Router &router : mRouters)
    {
        if (router.IsStateValid() && (router.GetLinkQualityIn() >= aLinkQuality))
        {
            count++;
        }
    }

    return count;
}

uint8_t RouterTable::GetLinkCost(const Router &aRouter) const
{
    uint8_t rval = Mle::kMaxRouteCost;

    VerifyOrExit(aRouter.GetRloc16() != Get<Mle::MleRouter>().GetRloc16() && aRouter.IsStateValid());

    rval = CostForLinkQuality(aRouter.GetTwoWayLinkQuality());

exit:
    return rval;
}

uint8_t RouterTable::GetLinkCost(uint8_t aRouterId) const
{
    uint8_t       rval = Mle::kMaxRouteCost;
    const Router *router;

    router = FindRouterById(aRouterId);

    // `nullptr` aRouterId indicates non-existing next hop, hence return kMaxRouteCost for it.
    VerifyOrExit(router != nullptr);

    rval = GetLinkCost(*router);

exit:
    return rval;
}

uint8_t RouterTable::GetPathCost(uint16_t aDestRloc16) const
{
    uint8_t  pathCost;
    uint16_t nextHopRloc16;

    GetNextHopAndPathCost(aDestRloc16, nextHopRloc16, pathCost);

    return pathCost;
}

uint8_t RouterTable::GetPathCostToLeader(void) const
{
    return GetPathCost(Mle::Rloc16FromRouterId(Get<Mle::Mle>().GetLeaderId()));
}

void RouterTable::GetNextHopAndPathCost(uint16_t aDestRloc16, uint16_t &aNextHopRloc16, uint8_t &aPathCost) const
{
    uint8_t       destRouterId;
    const Router *router;
    const Router *nextHop;

    aPathCost      = Mle::kMaxRouteCost;
    aNextHopRloc16 = Mle::kInvalidRloc16;

    VerifyOrExit(Get<Mle::Mle>().IsAttached());

    if (aDestRloc16 == Get<Mle::Mle>().GetRloc16())
    {
        // Destination is this device, return cost as zero.
        aPathCost      = 0;
        aNextHopRloc16 = aDestRloc16;
        ExitNow();
    }

    destRouterId = Mle::RouterIdFromRloc16(aDestRloc16);

    router  = FindRouterById(destRouterId);
    nextHop = (router != nullptr) ? FindNextHopOf(*router) : nullptr;

    if (Get<Mle::MleRouter>().IsChild())
    {
        const Router &parent = Get<Mle::Mle>().GetParent();

        if (parent.IsStateValid())
        {
            aNextHopRloc16 = parent.GetRloc16();
        }

        // If destination is our parent or another child of our
        // parent, we use the link cost to our parent. Otherwise we
        // check if we have a next hop towards the destination and
        // add its cost to the link cost to parent.

        VerifyOrExit((destRouterId == parent.GetRouterId()) || (nextHop != nullptr));

        aPathCost = CostForLinkQuality(parent.GetLinkQualityIn());

        if (destRouterId != parent.GetRouterId())
        {
            aPathCost += router->GetCost();
        }

        // The case where destination itself is a child is handled at
        // the end (after `else` block).
    }
    else // Role is router or leader
    {
        if (destRouterId == Mle::RouterIdFromRloc16(Get<Mle::Mle>().GetRloc16()))
        {
            // Destination is a one of our children.

            const Child *child = Get<ChildTable>().FindChild(aDestRloc16, Child::kInStateAnyExceptInvalid);

            VerifyOrExit(child != nullptr);
            aNextHopRloc16 = aDestRloc16;
            aPathCost      = CostForLinkQuality(child->GetLinkQualityIn());
            ExitNow();
        }

        VerifyOrExit(router != nullptr);

        aPathCost = GetLinkCost(*router);

        if (aPathCost < Mle::kMaxRouteCost)
        {
            aNextHopRloc16 = router->GetRloc16();
        }

        if (nextHop != nullptr)
        {
            // Determine whether direct link or forwarding hop link
            // through `nextHop` has a lower path cost.

            uint8_t nextHopPathCost = router->GetCost() + GetLinkCost(*nextHop);

            if (nextHopPathCost < aPathCost)
            {
                aPathCost      = nextHopPathCost;
                aNextHopRloc16 = nextHop->GetRloc16();
            }
        }
    }

    if (!Mle::IsActiveRouter(aDestRloc16))
    {
        // Destination is a child. we assume best link quality
        // between destination and its parent router.

        aPathCost += kCostForLinkQuality3;
    }

exit:
    return;
}

uint16_t RouterTable::GetNextHop(uint16_t aDestRloc16) const
{
    uint8_t  pathCost;
    uint16_t nextHopRloc16;

    GetNextHopAndPathCost(aDestRloc16, nextHopRloc16, pathCost);

    return nextHopRloc16;
}

void RouterTable::UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::RouterIdSet &aRouterIdSet)
{
    bool shouldAdd = false;

    mRouterIdSequence            = aRouterIdSequence;
    mRouterIdSequenceLastUpdated = TimerMilli::GetNow();

    // Remove all previously allocated routers that are now removed in
    // new `aRouterIdSet`.

    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        if (IsAllocated(routerId) == aRouterIdSet.Contains(routerId))
        {
            continue;
        }

        if (IsAllocated(routerId))
        {
            Router *router = FindRouterById(routerId);

            OT_ASSERT(router != nullptr);
            router->SetNextHopToInvalid();
            RemoveRouterLink(*router);
            RemoveRouter(*router);
        }
        else
        {
            shouldAdd = true;
        }
    }

    VerifyOrExit(shouldAdd);

    // Now add all new routers in `aRouterIdSet`.

    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        if (!IsAllocated(routerId) && aRouterIdSet.Contains(routerId))
        {
            AddRouter(routerId);
        }
    }

    Get<Mle::MleRouter>().ResetAdvertiseInterval();

exit:
    return;
}

void RouterTable::UpdateRoutes(const Mle::RouteTlv &aRouteTlv, uint8_t aNeighborId)
{
    Router          *neighbor;
    Mle::RouterIdSet finitePathCostIdSet;
    uint8_t          linkCostToNeighbor;

    neighbor = FindRouterById(aNeighborId);
    VerifyOrExit(neighbor != nullptr);

    // Before updating the routes, we track which routers have finite
    // path cost. After the update we check again to see if any path
    // cost changed from finite to infinite or vice versa to decide
    // whether to reset the  MLE Advertisement interval.

    finitePathCostIdSet.Clear();

    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        if (GetPathCost(Mle::Rloc16FromRouterId(routerId)) < Mle::kMaxRouteCost)
        {
            finitePathCostIdSet.Add(routerId);
        }
    }

    // Find the entry corresponding to our Router ID in the received
    // `aRouteTlv` to get the `LinkQualityIn` from the perspective of
    // neighbor. We use this to update our `LinkQualityOut` to the
    // neighbor.

    for (uint8_t routerId = 0, index = 0; routerId <= Mle::kMaxRouterId;
         index += aRouteTlv.IsRouterIdSet(routerId) ? 1 : 0, routerId++)
    {
        if (routerId != Mle::RouterIdFromRloc16(Get<Mle::Mle>().GetRloc16()))
        {
            continue;
        }

        if (aRouteTlv.IsRouterIdSet(routerId))
        {
            LinkQuality linkQuality = aRouteTlv.GetLinkQualityIn(index);

            if (neighbor->GetLinkQualityOut() != linkQuality)
            {
                neighbor->SetLinkQualityOut(linkQuality);
                SignalTableChanged();
            }
        }

        break;
    }

    linkCostToNeighbor = GetLinkCost(*neighbor);

    for (uint8_t routerId = 0, index = 0; routerId <= Mle::kMaxRouterId;
         index += aRouteTlv.IsRouterIdSet(routerId) ? 1 : 0, routerId++)
    {
        Router *router;
        Router *nextHop;
        uint8_t cost;

        if (!aRouteTlv.IsRouterIdSet(routerId))
        {
            continue;
        }

        router = FindRouterById(routerId);

        if (router == nullptr || router->GetRloc16() == Get<Mle::Mle>().GetRloc16() || router == neighbor)
        {
            continue;
        }

        nextHop = FindNextHopOf(*router);

        cost = aRouteTlv.GetRouteCost(index);
        cost = (cost == 0) ? Mle::kMaxRouteCost : cost;

        if ((nextHop == nullptr) || (nextHop == neighbor))
        {
            // `router` has no next hop or next hop is neighbor (sender)

            if (cost + linkCostToNeighbor < Mle::kMaxRouteCost)
            {
                if (router->SetNextHopAndCost(aNeighborId, cost))
                {
                    SignalTableChanged();
                }
            }
            else if (nextHop == neighbor)
            {
                router->SetNextHopToInvalid();
                router->SetLastHeard(TimerMilli::GetNow());
                SignalTableChanged();
            }
        }
        else
        {
            uint8_t curCost = router->GetCost() + GetLinkCost(*nextHop);
            uint8_t newCost = cost + linkCostToNeighbor;

            if (newCost < curCost)
            {
                router->SetNextHopAndCost(aNeighborId, cost);
                SignalTableChanged();
            }
        }
    }

    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        bool oldCostFinite = finitePathCostIdSet.Contains(routerId);
        bool newCostFinite = (GetPathCost(Mle::Rloc16FromRouterId(routerId)) < Mle::kMaxRouteCost);

        if (newCostFinite != oldCostFinite)
        {
            Get<Mle::MleRouter>().ResetAdvertiseInterval();
            break;
        }
    }

exit:
    return;
}

void RouterTable::UpdateRoutesOnFed(const Mle::RouteTlv &aRouteTlv, uint8_t aParentId)
{
    for (uint8_t routerId = 0, index = 0; routerId <= Mle::kMaxRouterId;
         index += aRouteTlv.IsRouterIdSet(routerId) ? 1 : 0, routerId++)
    {
        Router *router;
        uint8_t cost;
        uint8_t nextHopId;

        if (!aRouteTlv.IsRouterIdSet(routerId) || (routerId == aParentId))
        {
            continue;
        }

        router = FindRouterById(routerId);

        if (router == nullptr)
        {
            continue;
        }

        cost      = aRouteTlv.GetRouteCost(index);
        nextHopId = (cost == 0) ? Mle::kInvalidRouterId : aParentId;

        if (router->SetNextHopAndCost(nextHopId, cost))
        {
            SignalTableChanged();
        }
    }
}

void RouterTable::FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighbor) const
{
    uint8_t          routerIdSequence = mRouterIdSequence;
    Mle::RouterIdSet routerIdSet;
    uint8_t          routerIndex;

    mRouterIdMap.GetAsRouterIdSet(routerIdSet);

    if ((aNeighbor != nullptr) && Mle::IsActiveRouter(aNeighbor->GetRloc16()))
    {
        // Sending a Link Accept message that may require truncation
        // of Route64 TLV.

        uint8_t routerCount = mRouters.GetLength();

        if (routerCount > kMaxRoutersInRouteTlvForLinkAccept)
        {
            for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
            {
                if (routerCount <= kMaxRoutersInRouteTlvForLinkAccept)
                {
                    break;
                }

                if ((routerId == Mle::RouterIdFromRloc16(Get<Mle::Mle>().GetRloc16())) ||
                    (routerId == aNeighbor->GetRouterId()) || (routerId == Get<Mle::Mle>().GetLeaderId()))
                {
                    // Route64 TLV must contain this device and the
                    // neighboring router to ensure that at least this
                    // link can be established.
                    continue;
                }

                if (routerIdSet.Contains(routerId))
                {
                    routerIdSet.Remove(routerId);
                    routerCount--;
                }
            }

            // Ensure that the neighbor will process the current
            // Route64 TLV in a subsequent message exchange
            routerIdSequence -= kLinkAcceptSequenceRollback;
        }
    }

    aRouteTlv.SetRouterIdSequence(routerIdSequence);
    aRouteTlv.SetRouterIdMask(routerIdSet);

    routerIndex = 0;

    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        uint16_t routerRloc16;

        if (!routerIdSet.Contains(routerId))
        {
            continue;
        }

        routerRloc16 = Mle::Rloc16FromRouterId(routerId);

        if (routerRloc16 == Get<Mle::Mle>().GetRloc16())
        {
            aRouteTlv.SetRouteData(routerIndex, kLinkQuality0, kLinkQuality0, 1);
        }
        else
        {
            const Router *router = FindRouterById(routerId);
            uint8_t       pathCost;

            OT_ASSERT(router != nullptr);

            pathCost = GetPathCost(routerRloc16);

            if (pathCost >= Mle::kMaxRouteCost)
            {
                pathCost = 0;
            }

            aRouteTlv.SetRouteData(routerIndex, router->GetLinkQualityIn(), router->GetLinkQualityOut(), pathCost);
        }

        routerIndex++;
    }

    aRouteTlv.SetRouteDataLength(routerIndex);
}

void RouterTable::HandleTimeTick(void)
{
    mRouterIdMap.HandleTimeTick();

    VerifyOrExit(Get<Mle::MleRouter>().IsLeader());

    // Update router id sequence
    if (GetLeaderAge() >= kRouterIdSequencePeriod)
    {
        mRouterIdSequence++;
        mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
    }

exit:
    return;
}

#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
void RouterTable::GetRouterIdRange(uint8_t &aMinRouterId, uint8_t &aMaxRouterId) const
{
    aMinRouterId = mMinRouterId;
    aMaxRouterId = mMaxRouterId;
}

Error RouterTable::SetRouterIdRange(uint8_t aMinRouterId, uint8_t aMaxRouterId)
{
    Error error = kErrorNone;

    VerifyOrExit(aMinRouterId <= aMaxRouterId, error = kErrorInvalidArgs);
    VerifyOrExit(aMaxRouterId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
    mMinRouterId = aMinRouterId;
    mMaxRouterId = aMaxRouterId;

exit:
    return error;
}
#endif

void RouterTable::RouterIdMap::GetAsRouterIdSet(Mle::RouterIdSet &aRouterIdSet) const
{
    aRouterIdSet.Clear();

    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        if (IsAllocated(routerId))
        {
            aRouterIdSet.Add(routerId);
        }
    }
}

void RouterTable::RouterIdMap::HandleTimeTick(void)
{
    for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
    {
        // If Router ID is not allocated the `mIndexes` tracks the
        // remaining reuse delay time in seconds.

        if (!IsAllocated(routerId) && (mIndexes[routerId] > 0))
        {
            mIndexes[routerId]--;
        }
    }
}

void RouterTable::SignalTableChanged(void) { mChangedTask.Post(); }

void RouterTable::HandleTableChanged(void)
{
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
    LogRouteTable();
#endif

#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
    Get<Utils::HistoryTracker>().RecordRouterTableChange();
#endif

    Get<Mle::MleRouter>().UpdateAdvertiseInterval();
}

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
void RouterTable::LogRouteTable(void) const
{
    static constexpr uint16_t kStringSize = 128;

    LogInfo("Route table");

    for (const Router &router : mRouters)
    {
        String<kStringSize> string;

        string.Append("    %2d 0x%04x", router.GetRouterId(), router.GetRloc16());

        if (router.GetRloc16() == Get<Mle::Mle>().GetRloc16())
        {
            string.Append(" - me");
        }
        else if (Get<Mle::Mle>().IsChild() && (router.GetRloc16() == Get<Mle::Mle>().GetParent().GetRloc16()))
        {
            string.Append(" - parent");
        }
        else
        {
            if (router.IsStateValid())
            {
                string.Append(" - nbr{lq[i/o]:%d/%d cost:%d}", router.GetLinkQualityIn(), router.GetLinkQualityOut(),
                              GetLinkCost(router));
            }

            if (router.GetNextHop() != Mle::kInvalidRouterId)
            {
                string.Append(" - nexthop{%d cost:%d}", router.GetNextHop(), router.GetCost());
            }
        }

        if (router.GetRouterId() == Get<Mle::Mle>().GetLeaderId())
        {
            string.Append(" - leader");
        }

        LogInfo("%s", string.AsCString());
    }
}
#endif

} // namespace ot

#endif // OPENTHREAD_FTD
