/*
 *  Copyright (c) 2020, 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.
 */

/**
 * @file
 *   This file implements Thread NdProxy Table management.
 */

#include "ndproxy_table.hpp"

#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE

#include "common/array.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"

namespace ot {

namespace BackboneRouter {

RegisterLogModule("BbrNdProxy");

void NdProxyTable::NdProxy::Init(const Ip6::InterfaceIdentifier &aAddressIid,
                                 const Ip6::InterfaceIdentifier &aMeshLocalIid,
                                 uint16_t                        aRloc16,
                                 uint32_t                        aTimeSinceLastTransaction)
{
    OT_ASSERT(!mValid);

    Clear();

    mValid        = true;
    mAddressIid   = aAddressIid;
    mMeshLocalIid = aMeshLocalIid;
    mDadFlag      = true;

    Update(aRloc16, aTimeSinceLastTransaction);
}

void NdProxyTable::NdProxy::Update(uint16_t aRloc16, uint32_t aTimeSinceLastTransaction)
{
    OT_ASSERT(mValid);

    mRloc16 = aRloc16;
    aTimeSinceLastTransaction =
        OT_MIN(aTimeSinceLastTransaction, static_cast<uint32_t>(Mle::kTimeSinceLastTransactionMax));
    mLastRegistrationTime = TimerMilli::GetNow() - TimeMilli::SecToMsec(aTimeSinceLastTransaction);
}

bool NdProxyTable::MatchesFilter(const NdProxy &aProxy, Filter aFilter)
{
    bool rval = false;

    switch (aFilter)
    {
    case kFilterInvalid:
        rval = !aProxy.mValid;
        break;
    case kFilterValid:
        rval = aProxy.mValid;
        break;
    case kFilterDadInProcess:
        rval = aProxy.mValid && aProxy.mDadFlag;
        break;
    }

    return rval;
}

NdProxyTable::Iterator::Iterator(Instance &aInstance, Filter aFilter)
    : InstanceLocator(aInstance)
    , mFilter(aFilter)
{
    NdProxyTable &table = GetInstance().Get<BackboneRouter::NdProxyTable>();

    mItem = &table.mProxies[0];

    if (!MatchesFilter(*mItem, mFilter))
    {
        Advance();
    }
}

NdProxyTable::Iterator::Iterator(Instance &aInstance, NdProxyTable::Iterator::IteratorType)
    : InstanceLocator(aInstance)
{
    NdProxyTable &table = GetInstance().Get<BackboneRouter::NdProxyTable>();
    mItem               = GetArrayEnd(table.mProxies);
}

void NdProxyTable::Iterator::Advance(void)
{
    NdProxyTable &table = GetInstance().Get<BackboneRouter::NdProxyTable>();

    do
    {
        mItem++;
    } while (mItem < GetArrayEnd(table.mProxies) && !MatchesFilter(*mItem, mFilter));
}

void NdProxyTable::Erase(NdProxy &aNdProxy)
{
    aNdProxy.mValid = false;
}

void NdProxyTable::HandleDomainPrefixUpdate(Leader::DomainPrefixState aState)
{
    if (aState == Leader::kDomainPrefixAdded || aState == Leader::kDomainPrefixRemoved ||
        aState == Leader::kDomainPrefixRefreshed)
    {
        Clear();
    }
}

void NdProxyTable::Clear(void)
{
    for (NdProxy &proxy : mProxies)
    {
        proxy.Clear();
    }

    if (mCallback != nullptr)
    {
        mCallback(mCallbackContext, OT_BACKBONE_ROUTER_NDPROXY_CLEARED, nullptr);
    }

    LogInfo("NdProxyTable::Clear!");
}

Error NdProxyTable::Register(const Ip6::InterfaceIdentifier &aAddressIid,
                             const Ip6::InterfaceIdentifier &aMeshLocalIid,
                             uint16_t                        aRloc16,
                             const uint32_t *                aTimeSinceLastTransaction)
{
    Error    error                    = kErrorNone;
    NdProxy *proxy                    = FindByAddressIid(aAddressIid);
    uint32_t timeSinceLastTransaction = aTimeSinceLastTransaction == nullptr ? 0 : *aTimeSinceLastTransaction;

    if (proxy != nullptr)
    {
        VerifyOrExit(proxy->mMeshLocalIid == aMeshLocalIid, error = kErrorDuplicated);

        proxy->Update(aRloc16, timeSinceLastTransaction);
        NotifyDuaRegistrationOnBackboneLink(*proxy, /* aIsRenew */ true);
        ExitNow();
    }

    proxy = FindByMeshLocalIid(aMeshLocalIid);
    if (proxy != nullptr)
    {
        TriggerCallback(OT_BACKBONE_ROUTER_NDPROXY_REMOVED, proxy->mAddressIid);
        Erase(*proxy);
    }
    else
    {
        proxy = FindInvalid();

        // TODO: evict stale DUA entries to have room for this new DUA.
        VerifyOrExit(proxy != nullptr, error = kErrorNoBufs);
    }

    proxy->Init(aAddressIid, aMeshLocalIid, aRloc16, timeSinceLastTransaction);
    mIsAnyDadInProcess = true;

exit:
    LogInfo("NdProxyTable::Register %s MLIID %s RLOC16 %04x LTT %u => %s", aAddressIid.ToString().AsCString(),
            aMeshLocalIid.ToString().AsCString(), aRloc16, timeSinceLastTransaction, ErrorToString(error));
    return error;
}

NdProxyTable::NdProxy *NdProxyTable::FindByAddressIid(const Ip6::InterfaceIdentifier &aAddressIid)
{
    NdProxy *found = nullptr;

    for (NdProxy &proxy : Iterate(kFilterValid))
    {
        if (proxy.mAddressIid == aAddressIid)
        {
            ExitNow(found = &proxy);
        }
    }

exit:
    LogDebg("NdProxyTable::FindByAddressIid(%s) => %s", aAddressIid.ToString().AsCString(),
            found ? found->mMeshLocalIid.ToString().AsCString() : "NOT_FOUND");
    return found;
}

NdProxyTable::NdProxy *NdProxyTable::FindByMeshLocalIid(const Ip6::InterfaceIdentifier &aMeshLocalIid)
{
    NdProxy *found = nullptr;

    for (NdProxy &proxy : Iterate(kFilterValid))
    {
        if (proxy.mMeshLocalIid == aMeshLocalIid)
        {
            ExitNow(found = &proxy);
        }
    }

exit:
    LogDebg("NdProxyTable::FindByMeshLocalIid(%s) => %s", aMeshLocalIid.ToString().AsCString(),
            found ? found->mAddressIid.ToString().AsCString() : "NOT_FOUND");
    return found;
}

NdProxyTable::NdProxy *NdProxyTable::FindInvalid(void)
{
    NdProxy *found = nullptr;

    for (NdProxy &proxy : Iterate(kFilterInvalid))
    {
        ExitNow(found = &proxy);
    }

exit:
    LogDebg("NdProxyTable::FindInvalid() => %s", found ? "OK" : "NOT_FOUND");
    return found;
}

void NdProxyTable::HandleTimer(void)
{
    VerifyOrExit(mIsAnyDadInProcess);

    mIsAnyDadInProcess = false;

    for (NdProxy &proxy : Iterate(kFilterDadInProcess))
    {
        if (proxy.IsDadAttamptsComplete())
        {
            proxy.mDadFlag = false;
            NotifyDuaRegistrationOnBackboneLink(proxy, /* aIsRenew */ false);
        }
        else
        {
            mIsAnyDadInProcess = true;

            if (Get<BackboneRouter::Manager>().SendBackboneQuery(GetDua(proxy)) == kErrorNone)
            {
                proxy.IncreaseDadAttampts();
            }
        }
    }

exit:
    return;
}

void NdProxyTable::SetCallback(otBackboneRouterNdProxyCallback aCallback, void *aContext)
{
    mCallback        = aCallback;
    mCallbackContext = aContext;
}

void NdProxyTable::TriggerCallback(otBackboneRouterNdProxyEvent    aEvent,
                                   const Ip6::InterfaceIdentifier &aAddressIid) const
{
    Ip6::Address       dua;
    const Ip6::Prefix *prefix = Get<BackboneRouter::Leader>().GetDomainPrefix();

    VerifyOrExit(mCallback != nullptr);

    OT_ASSERT(prefix != nullptr);

    dua.SetPrefix(*prefix);
    dua.SetIid(aAddressIid);

    mCallback(mCallbackContext, aEvent, &dua);

exit:
    return;
}

void NdProxyTable::NotifyDadComplete(NdProxyTable::NdProxy &aNdProxy, bool aDuplicated)
{
    if (aDuplicated)
    {
        Erase(aNdProxy);
    }
    else
    {
        aNdProxy.mDadAttempts = Mle::kDuaDadRepeats;
    }
}

Ip6::Address NdProxyTable::GetDua(NdProxy &aNdProxy)
{
    Ip6::Address       dua;
    const Ip6::Prefix *domainPrefix = Get<BackboneRouter::Leader>().GetDomainPrefix();

    OT_ASSERT(domainPrefix != nullptr);

    dua.SetPrefix(*domainPrefix);
    dua.SetIid(aNdProxy.mAddressIid);

    return dua;
}

NdProxyTable::NdProxy *NdProxyTable::ResolveDua(const Ip6::Address &aDua)
{
    return Get<Leader>().IsDomainUnicast(aDua) ? FindByAddressIid(aDua.GetIid()) : nullptr;
}

void NdProxyTable::NotifyDuaRegistrationOnBackboneLink(NdProxyTable::NdProxy &aNdProxy, bool aIsRenew)
{
    if (!aNdProxy.mDadFlag)
    {
        TriggerCallback(aIsRenew ? OT_BACKBONE_ROUTER_NDPROXY_RENEWED : OT_BACKBONE_ROUTER_NDPROXY_ADDED,
                        aNdProxy.mAddressIid);

        IgnoreError(Get<BackboneRouter::Manager>().SendProactiveBackboneNotification(
            GetDua(aNdProxy), aNdProxy.GetMeshLocalIid(), aNdProxy.GetTimeSinceLastTransaction()));
    }
}

Error NdProxyTable::GetInfo(const Ip6::Address &aDua, otBackboneRouterNdProxyInfo &aNdProxyInfo)
{
    Error error = kErrorNotFound;

    VerifyOrExit(Get<Leader>().IsDomainUnicast(aDua), error = kErrorInvalidArgs);

    for (NdProxy &proxy : Iterate(kFilterValid))
    {
        if (proxy.mAddressIid == aDua.GetIid())
        {
            aNdProxyInfo.mMeshLocalIid             = &proxy.mMeshLocalIid;
            aNdProxyInfo.mTimeSinceLastTransaction = proxy.GetTimeSinceLastTransaction();
            aNdProxyInfo.mRloc16                   = proxy.mRloc16;

            ExitNow(error = kErrorNone);
        }
    }

exit:
    return error;
}

} // namespace BackboneRouter

} // namespace ot

#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
