/*
 *  Copyright (c) 2019, 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 includes implementation of radio selector (for multi radio links).
 */

#include "radio_selector.hpp"

#if OPENTHREAD_CONFIG_MULTI_RADIO

#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"

namespace ot {

RegisterLogModule("RadioSelector");

// This array defines the order in which different radio link types are
// selected for message tx (direct message).
const Mac::RadioType RadioSelector::sRadioSelectionOrder[Mac::kNumRadioTypes] = {
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    Mac::kRadioTypeTrel,
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    Mac::kRadioTypeIeee802154,
#endif
};

RadioSelector::RadioSelector(Instance &aInstance)
    : InstanceLocator(aInstance)
{
}

void RadioSelector::NeighborInfo::PopulateMultiRadioInfo(MultiRadioInfo &aInfo)
{
    memset(&aInfo, 0, sizeof(MultiRadioInfo));

#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
    if (GetSupportedRadioTypes().Contains(Mac::kRadioTypeIeee802154))
    {
        aInfo.mSupportsIeee802154         = true;
        aInfo.mIeee802154Info.mPreference = GetRadioPreference(Mac::kRadioTypeIeee802154);
    }
#endif

#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    if (GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel))
    {
        aInfo.mSupportsTrelUdp6         = true;
        aInfo.mTrelUdp6Info.mPreference = GetRadioPreference(Mac::kRadioTypeTrel);
    }
#endif
}

LogLevel RadioSelector::UpdatePreference(Neighbor &aNeighbor, Mac::RadioType aRadioType, int16_t aDifference)
{
    uint8_t old        = aNeighbor.GetRadioPreference(aRadioType);
    int16_t preferecne = static_cast<int16_t>(old);

    preferecne += aDifference;

    if (preferecne > kMaxPreference)
    {
        preferecne = kMaxPreference;
    }

    if (preferecne < kMinPreference)
    {
        preferecne = kMinPreference;
    }

    aNeighbor.SetRadioPreference(aRadioType, static_cast<uint8_t>(preferecne));

    // We check whether the update to the preference value caused it
    // to cross the threshold `kHighPreference`. Based on this we
    // return a suggested log level. If there is cross, suggest info
    // log level, otherwise debug log level.

    return ((old >= kHighPreference) != (preferecne >= kHighPreference)) ? kLogLevelInfo : kLogLevelDebg;
}

void RadioSelector::UpdateOnReceive(Neighbor &aNeighbor, Mac::RadioType aRadioType, bool aIsDuplicate)
{
    LogLevel logLevel = kLogLevelInfo;

    if (aNeighbor.GetSupportedRadioTypes().Contains(aRadioType))
    {
        logLevel = UpdatePreference(aNeighbor, aRadioType,
                                    aIsDuplicate ? kPreferenceChangeOnRxDuplicate : kPreferenceChangeOnRx);

        Log(logLevel, aIsDuplicate ? "UpdateOnDupRx" : "UpdateOnRx", aRadioType, aNeighbor);
    }
    else
    {
        aNeighbor.AddSupportedRadioType(aRadioType);
        aNeighbor.SetRadioPreference(aRadioType, kInitPreference);

        Log(logLevel, "NewRadio(OnRx)", aRadioType, aNeighbor);
    }
}

void RadioSelector::UpdateOnSendDone(Mac::TxFrame &aFrame, Error aTxError)
{
    LogLevel       logLevel  = kLogLevelInfo;
    Mac::RadioType radioType = aFrame.GetRadioType();
    Mac::Address   macDest;
    Neighbor *     neighbor;

#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    if (radioType == Mac::kRadioTypeTrel)
    {
        // TREL radio link uses deferred ack model. We ignore
        // `SendDone` event from `Mac` layer with success status and
        // wait for deferred ack callback.
        VerifyOrExit(aTxError != kErrorNone);
    }
#endif

    VerifyOrExit(aFrame.GetAckRequest());

    IgnoreError(aFrame.GetDstAddr(macDest));
    neighbor = Get<NeighborTable>().FindNeighbor(macDest, Neighbor::kInStateAnyExceptInvalid);
    VerifyOrExit(neighbor != nullptr);

    if (neighbor->GetSupportedRadioTypes().Contains(radioType))
    {
        logLevel = UpdatePreference(
            *neighbor, radioType, (aTxError == kErrorNone) ? kPreferenceChangeOnTxSuccess : kPreferenceChangeOnTxError);

        Log(logLevel, (aTxError == kErrorNone) ? "UpdateOnTxSucc" : "UpdateOnTxErr", radioType, *neighbor);
    }
    else
    {
        VerifyOrExit(aTxError == kErrorNone);
        neighbor->AddSupportedRadioType(radioType);
        neighbor->SetRadioPreference(radioType, kInitPreference);

        Log(logLevel, "NewRadio(OnTx)", radioType, *neighbor);
    }

exit:
    return;
}

#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
void RadioSelector::UpdateOnDeferredAck(Neighbor &aNeighbor, Error aTxError, bool &aAllowNeighborRemove)
{
    LogLevel logLevel = kLogLevelInfo;

    aAllowNeighborRemove = true;

    if (aNeighbor.GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel))
    {
        logLevel = UpdatePreference(aNeighbor, Mac::kRadioTypeTrel,
                                    (aTxError == kErrorNone) ? kPreferenceChangeOnDeferredAckSuccess
                                                             : kPreferenceChangeOnDeferredAckTimeout);

        Log(logLevel, (aTxError == kErrorNone) ? "UpdateOnDefAckSucc" : "UpdateOnDefAckFail", Mac::kRadioTypeTrel,
            aNeighbor);

        // In case of deferred ack timeout, we check if the neighbor
        // has any other radio link (with high preference) for future
        // tx. If it it does, we set `aAllowNeighborRemove` to `false`
        // to ensure neighbor is not removed yet.

        VerifyOrExit(aTxError != kErrorNone);

        for (Mac::RadioType radio : sRadioSelectionOrder)
        {
            if ((radio != Mac::kRadioTypeTrel) && aNeighbor.GetSupportedRadioTypes().Contains(radio) &&
                aNeighbor.GetRadioPreference(radio) >= kHighPreference)
            {
                aAllowNeighborRemove = false;
                ExitNow();
            }
        }
    }
    else
    {
        VerifyOrExit(aTxError == kErrorNone);
        aNeighbor.AddSupportedRadioType(Mac::kRadioTypeTrel);
        aNeighbor.SetRadioPreference(Mac::kRadioTypeTrel, kInitPreference);

        Log(logLevel, "NewRadio(OnDefAckSucc)", Mac::kRadioTypeTrel, aNeighbor);
    }

exit:
    return;
}
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE

Mac::RadioType RadioSelector::Select(Mac::RadioTypes aRadioOptions, const Neighbor &aNeighbor)
{
    Mac::RadioType selectedRadio      = sRadioSelectionOrder[0];
    uint8_t        selectedPreference = 0;
    bool           found              = false;

    // Select the first radio links with preference higher than
    // threshold `kHighPreference`. The radio links are checked in the
    // order defined by the `sRadioSelectionOrder` array. If no radio
    // link has preference higher then threshold, select the one with
    // highest preference.

    for (Mac::RadioType radio : sRadioSelectionOrder)
    {
        if (aRadioOptions.Contains(radio))
        {
            uint8_t preference = aNeighbor.GetRadioPreference(radio);

            if (preference >= kHighPreference)
            {
                selectedRadio = radio;
                break;
            }

            if (!found || (selectedPreference < preference))
            {
                found              = true;
                selectedRadio      = radio;
                selectedPreference = preference;
            }
        }
    }

    return selectedRadio;
}

Mac::TxFrame &RadioSelector::SelectRadio(Message &aMessage, const Mac::Address &aMacDest, Mac::TxFrames &aTxFrames)
{
    Neighbor *      neighbor;
    Mac::RadioType  selectedRadio;
    Mac::RadioTypes selections;

    if (aMacDest.IsBroadcast() || aMacDest.IsNone())
    {
        aMessage.ClearRadioType();
        ExitNow(selections.AddAll());
    }

    // If the radio type is already set when message was created we
    // use the selected radio type. (e.g., MLE Discovery Response
    // selects the radio link from which MLE Discovery Request is
    // received.

    if (aMessage.IsRadioTypeSet())
    {
        ExitNow(selections.Add(aMessage.GetRadioType()));
    }

    neighbor = Get<NeighborTable>().FindNeighbor(aMacDest, Neighbor::kInStateAnyExceptInvalid);

    if ((neighbor == nullptr) || neighbor->GetSupportedRadioTypes().IsEmpty())
    {
        // If we do not have a corresponding neighbor or do not yet
        // know the supported radio types, we try sending on all radio
        // links in parallel. As an example, such a situation can
        // happen when recovering a non-sleepy child (sending MLE
        // Child Update Request to it) after device itself was reset.

        aMessage.ClearRadioType();
        ExitNow(selections.AddAll());
    }

    selectedRadio = Select(neighbor->GetSupportedRadioTypes(), *neighbor);
    selections.Add(selectedRadio);

    Log(kLogLevelDebg, "SelectRadio", selectedRadio, *neighbor);

    aMessage.SetRadioType(selectedRadio);

    // We (probabilistically) decide whether to probe on another radio
    // link for the current frame tx. When probing we allow the same
    // frame to be sent in parallel over multiple radio links but only
    // care about the tx outcome (ack status) on the main selected
    // radio link. This is done by setting the "required radio types"
    // (`SetRequiredRadioTypes()`) to match the main selection on
    // `aTxFrames`. We allow probe on TREL radio link if it is not
    // currently usable (thus not selected) but is/was supported by
    // the neighbor (i.e., we did rx/tx on TREL link from/to this
    // neighbor in the past). The probe process helps detect whether
    // the TREL link is usable again allowing us to switch over
    // faster.

#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
    if (!selections.Contains(Mac::kRadioTypeTrel) && neighbor->GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel) &&
        (Random::NonCrypto::GetUint8InRange(0, 100) < kTrelProbeProbability))
    {
        aTxFrames.SetRequiredRadioTypes(selections);
        selections.Add(Mac::kRadioTypeTrel);

        Log(kLogLevelDebg, "Probe", Mac::kRadioTypeTrel, *neighbor);
    }
#endif

exit:
    return aTxFrames.GetTxFrame(selections);
}

Mac::RadioType RadioSelector::SelectPollFrameRadio(const Neighbor &aParent)
{
    // This array defines the order in which different radio link types
    // are selected for data poll frame tx.
    static const Mac::RadioType selectionOrder[Mac::kNumRadioTypes] = {
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
        Mac::kRadioTypeIeee802154,
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
        Mac::kRadioTypeTrel,
#endif
    };

    Mac::RadioType selection = selectionOrder[0];

    for (Mac::RadioType radio : selectionOrder)
    {
        if (aParent.GetSupportedRadioTypes().Contains(radio))
        {
            selection = radio;
            break;
        }
    }

    return selection;
}

// LCOV_EXCL_START

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)

void RadioSelector::Log(LogLevel        aLogLevel,
                        const char *    aActionText,
                        Mac::RadioType  aRadioType,
                        const Neighbor &aNeighbor)
{
    String<kRadioPreferenceStringSize> preferenceString;
    bool                               isFirstEntry = true;

    VerifyOrExit(Instance::GetLogLevel() >= aLogLevel);

    for (Mac::RadioType radio : sRadioSelectionOrder)
    {
        if (aNeighbor.GetSupportedRadioTypes().Contains(radio))
        {
            preferenceString.Append("%s%s:%d", isFirstEntry ? "" : " ", RadioTypeToString(radio),
                                    aNeighbor.GetRadioPreference(radio));
            isFirstEntry = false;
        }
    }

    LogAt(aLogLevel, "RadioSelector: %s %s - neighbor:[%s rloc16:0x%04x radio-pref:{%s} state:%s]", aActionText,
          RadioTypeToString(aRadioType), aNeighbor.GetExtAddress().ToString().AsCString(), aNeighbor.GetRloc16(),
          preferenceString.AsCString(), Neighbor::StateToString(aNeighbor.GetState()));

exit:
    return;
}

#else // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)

void RadioSelector::Log(LogLevel, const char *, Mac::RadioType, const Neighbor &)
{
}

#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)

// LCOV_EXCL_STOP

} // namespace ot

#endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
