/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      Implementation of SetUp Code Pairer, a class that parses a given
 *      setup code and uses the extracted informations to discover and
 *      filter commissionables nodes, before initiating the pairing process.
 *
 */

#include <controller/SetUpCodePairer.h>

#include <controller/CHIPDeviceController.h>
#include <lib/dnssd/Resolver.h>
#include <lib/support/CodeUtils.h>
#include <memory>
#include <platform/internal/NFCCommissioningManager.h>
#include <system/SystemClock.h>
#include <tracing/metric_event.h>
#include <vector>

constexpr uint32_t kDeviceDiscoveredTimeout = CHIP_CONFIG_SETUP_CODE_PAIRER_DISCOVERY_TIMEOUT_SECS * chip::kMillisecondsPerSecond;

using namespace chip::Tracing;

namespace chip {
namespace Controller {

CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission,
                                       DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData)
{
    VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, remoteId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);

    std::vector<SetupPayload> payloads;
    ReturnErrorOnFailure(SetupPayload::FromStringRepresentation(setUpCode, payloads));

    // If the caller has provided a specific single resolution data, and we were
    // only looking for one commissionee, and the caller says that the provided
    // data matches that one commissionee, just go ahead and use the provided data.
    //
    // If we were looking for more than one device (i.e. if either of the
    // payload arrays involved does not have length 1), we can't make use of the
    // incoming resolution data, since it does not contain the long
    // discriminator of the thing that was discovered, and therefore we can't
    // tell which setup passcode to use for it.
    if (resolutionData.HasValue() && payloads.size() == 1 && mSetupPayloads.size() == 1)
    {
        VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, discoveryType != DiscoveryType::kAll,
                                      CHIP_ERROR_INVALID_ARGUMENT);
        if (mRemoteId == remoteId && mSetupPayloads[0].setUpPINCode == payloads[0].setUpPINCode && mConnectionType == commission &&
            mDiscoveryType == discoveryType)
        {
            // Not passing a discriminator is ok, since we have only one payload.
            NotifyCommissionableDeviceDiscovered(resolutionData.Value(), /* matchedLongDiscriminator = */ std::nullopt);
            return CHIP_NO_ERROR;
        }
    }

    ResetDiscoveryState();

    mConnectionType = commission;
    mDiscoveryType  = discoveryType;
    mRemoteId       = remoteId;
    mSetupPayloads  = std::move(payloads);

    if (resolutionData.HasValue() && mSetupPayloads.size() == 1)
    {
        // No need to pass in a discriminator if we have only one payload, which
        // is good because we don't have a full discriminator here anyway.
        NotifyCommissionableDeviceDiscovered(resolutionData.Value(), /* matchedLongDiscriminator = */ std::nullopt);
        return CHIP_NO_ERROR;
    }

    ReturnErrorOnFailureWithMetric(kMetricSetupCodePairerPairDevice, Connect());
    auto errorCode =
        mSystemLayer->StartTimer(System::Clock::Milliseconds32(kDeviceDiscoveredTimeout), OnDeviceDiscoveredTimeoutCallback, this);
    if (CHIP_NO_ERROR == errorCode)
    {
        MATTER_LOG_METRIC_BEGIN(kMetricSetupCodePairerPairDevice);
    }
    return errorCode;
}

CHIP_ERROR SetUpCodePairer::Connect()
{
    if (mDiscoveryType == DiscoveryType::kAll)
    {
        if (ShouldDiscoverUsing(RendezvousInformationFlag::kBLE))
        {
            CHIP_ERROR err = StartDiscoveryOverBLE();
            if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
            {
                ChipLogProgress(Controller,
                                "Skipping commissionable node discovery over BLE since not supported by the controller!");
            }
            else if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller, "Failed to start commissionable node discovery over BLE: %" CHIP_ERROR_FORMAT,
                             err.Format());
            }
        }
        if (ShouldDiscoverUsing(RendezvousInformationFlag::kWiFiPAF))
        {
            CHIP_ERROR err = StartDiscoveryOverWiFiPAF();
            if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
            {
                ChipLogProgress(Controller,
                                "Skipping commissionable node discovery over Wi-Fi PAF since not supported by the controller!");
            }
            else if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller, "Failed to start commissionable node discovery over Wi-Fi PAF: %" CHIP_ERROR_FORMAT,
                             err.Format());
            }
        }
        if (ShouldDiscoverUsing(RendezvousInformationFlag::kNFC))
        {
            CHIP_ERROR err = StartDiscoveryOverNFC();
            if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
            {
                ChipLogProgress(Controller,
                                "Skipping commissionable node discovery over NFC since not supported by the controller!");
            }
            else if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller, "Failed to start commissionable node discovery over NFC: %" CHIP_ERROR_FORMAT,
                             err.Format());
            }
        }
    }

    // We always want to search on network because any node that has already been commissioned will use on-network regardless of the
    // QR code flag.
    CHIP_ERROR err = StartDiscoveryOverDNSSD();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "Failed to start commissionable node discovery over DNS-SD: %" CHIP_ERROR_FORMAT, err.Format());
    }
    return err;
}

CHIP_ERROR SetUpCodePairer::StartDiscoveryOverBLE()
{
#if CONFIG_NETWORK_LAYER_BLE
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
    VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
    mCommissioner->ConnectBleTransportToSelf();
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
    VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

    ChipLogProgress(Controller, "Starting commissionable node discovery over BLE");

    // Handle possibly-sync callbacks.
    mWaitingForDiscovery[kBLETransport] = true;
    CHIP_ERROR err;
    // Not all BLE backends support the new NewBleConnectionByDiscriminators
    // API, so use the old one when we can (i.e. when we only have one setup
    // payload), to avoid breaking existing API consumers.
    if (mSetupPayloads.size() == 1)
    {
        err = mBleLayer->NewBleConnectionByDiscriminator(mSetupPayloads[0].discriminator, this, OnDiscoveredDeviceOverBleSuccess,
                                                         OnDiscoveredDeviceOverBleError);
    }
    else
    {
        std::vector<SetupDiscriminator> discriminators;
        discriminators.reserve(mSetupPayloads.size());
        for (auto & payload : mSetupPayloads)
        {
            discriminators.emplace_back(payload.discriminator);
        }
        err = mBleLayer->NewBleConnectionByDiscriminators(Span(discriminators.data(), discriminators.size()), this,
                                                          OnDiscoveredDeviceWithDiscriminatorOverBleSuccess,
                                                          OnDiscoveredDeviceOverBleError);
    }
    if (err != CHIP_NO_ERROR)
    {
        mWaitingForDiscovery[kBLETransport] = false;
    }
    return err;
#else
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
#endif // CONFIG_NETWORK_LAYER_BLE
}

CHIP_ERROR SetUpCodePairer::StopDiscoveryOverBLE()
{
    // Make sure to not call CancelBleIncompleteConnection unless we are in fact
    // waiting on BLE discovery.  It will cancel connections that are in fact
    // completed. In particular, if we just established PASE over BLE calling
    // CancelBleIncompleteConnection here unconditionally would cancel the BLE
    // connection underlying the PASE session.  So make sure to only call
    // CancelBleIncompleteConnection if we're still waiting to hear back on the
    // BLE discovery bits.
    if (!mWaitingForDiscovery[kBLETransport])
    {
        return CHIP_NO_ERROR;
    }

    mWaitingForDiscovery[kBLETransport] = false;
#if CONFIG_NETWORK_LAYER_BLE
    VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
    ChipLogProgress(Controller, "Stopping commissionable node discovery over BLE");
    return mBleLayer->CancelBleIncompleteConnection();
#else
    return CHIP_NO_ERROR;
#endif // CONFIG_NETWORK_LAYER_BLE
}

CHIP_ERROR SetUpCodePairer::StartDiscoveryOverDNSSD()
{
    ChipLogProgress(Controller, "Starting commissionable node discovery over DNS-SD");

    Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kNone);
    if (mSetupPayloads.size() == 1)
    {
        auto & discriminator = mSetupPayloads[0].discriminator;
        if (discriminator.IsShortDiscriminator())
        {
            filter.type = Dnssd::DiscoveryFilterType::kShortDiscriminator;
            filter.code = discriminator.GetShortValue();
        }
        else
        {
            filter.type = Dnssd::DiscoveryFilterType::kLongDiscriminator;
            filter.code = discriminator.GetLongValue();
        }
    }

    // In theory we could try to filter on the vendor ID if it's the same across all the setup
    // payloads, but DNS-SD advertisements are not required to include the Vendor ID subtype, so in
    // practice that's not doable.

    // Handle possibly-sync callbacks.
    mWaitingForDiscovery[kIPTransport] = true;
    CHIP_ERROR err                     = mCommissioner->DiscoverCommissionableNodes(filter);
    if (err != CHIP_NO_ERROR)
    {
        mWaitingForDiscovery[kIPTransport] = false;
    }
    return err;
}

CHIP_ERROR SetUpCodePairer::StopDiscoveryOverDNSSD()
{
    ChipLogProgress(Controller, "Stopping commissionable node discovery over DNS-SD");

    mWaitingForDiscovery[kIPTransport] = false;

    return mCommissioner->StopCommissionableDiscovery();
}

CHIP_ERROR SetUpCodePairer::StartDiscoveryOverWiFiPAF()
{
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
    if (mSetupPayloads.size() != 1)
    {
        ChipLogError(Controller, "Wi-Fi PAF commissioning does not support concatenated QR codes yet.");
        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }

    auto & payload = mSetupPayloads[0];

    ChipLogProgress(Controller, "Starting commissionable node discovery over Wi-Fi PAF");
    VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);

    const SetupDiscriminator connDiscriminator(payload.discriminator);
    VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
                        ChipLogError(Controller, "Error, Long discriminator is required"));
    uint16_t discriminator              = connDiscriminator.GetLongValue();
    WiFiPAF::WiFiPAFSession sessionInfo = { .role          = WiFiPAF::WiFiPafRole::kWiFiPafRole_Subscriber,
                                            .nodeId        = mRemoteId,
                                            .discriminator = discriminator };
    ReturnErrorOnFailure(
        DeviceLayer::ConnectivityMgr().GetWiFiPAF()->AddPafSession(WiFiPAF::PafInfoAccess::kAccNodeInfo, sessionInfo));

    mWaitingForDiscovery[kWiFiPAFTransport] = true;
    CHIP_ERROR err = DeviceLayer::ConnectivityMgr().WiFiPAFSubscribe(discriminator, (void *) this, OnWiFiPAFSubscribeComplete,
                                                                     OnWiFiPAFSubscribeError);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed, err = %" CHIP_ERROR_FORMAT, err.Format());
        mWaitingForDiscovery[kWiFiPAFTransport] = false;
    }
    return err;
#else
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
}

CHIP_ERROR SetUpCodePairer::StopDiscoveryOverWiFiPAF()
{
    mWaitingForDiscovery[kWiFiPAFTransport] = false;
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
    return DeviceLayer::ConnectivityMgr().WiFiPAFCancelIncompleteSubscribe();
#else
    return CHIP_NO_ERROR;
#endif
}

CHIP_ERROR SetUpCodePairer::StartDiscoveryOverNFC()
{
#if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
    if (mSetupPayloads.size() != 1)
    {
        ChipLogError(Controller, "NFC commissioning does not support concatenated QR codes yet.");
        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }

    auto & payload = mSetupPayloads[0];

    ChipLogProgress(Controller, "Starting commissionable node discovery over NFC");
    VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);

    const SetupDiscriminator connDiscriminator(payload.discriminator);
    VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
                        ChipLogError(Controller, "Error, Long discriminator is required"));
    chip::Nfc::NFCTag::Identifier identifier  = { .discriminator = payload.discriminator.GetLongValue() };
    Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
    if (!readerTransport)
    {
        ChipLogError(Controller, "Commissionable node discovery over NFC since there is no valid NFC reader transport");
        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }

    readerTransport->SetDelegate(this);
    CHIP_ERROR err = readerTransport->StartDiscoveringTagMatchingAddress(identifier);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "Commissionable node discovery over NFC failed, err = %" CHIP_ERROR_FORMAT, err.Format());
    }
    else
    {
        mWaitingForDiscovery[kNFCTransport] = true;
    }
    return err;
#else
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
#endif // CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
}

CHIP_ERROR SetUpCodePairer::StopDiscoveryOverNFC()
{
#if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
    mWaitingForDiscovery[kNFCTransport] = false;

    Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
    if (!readerTransport)
    {
        ChipLogError(Controller,
                     "Failed to stop commissionable node discovery over NFC since there is no valid NFC reader transport");
        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }

    ChipLogProgress(Controller, "Stopping commissionable node discovery over NFC by removing delegate");
    readerTransport->SetDelegate(nullptr);
#endif
    return CHIP_NO_ERROR;
}

bool SetUpCodePairer::ConnectToDiscoveredDevice()
{
    if (mWaitingForPASE)
    {
        // Nothing to do.  Just wait until we either succeed or fail at that
        // PASE session establishment.
        return false;
    }

    while (!mDiscoveredParameters.empty())
    {
        mCurrentPASEPayload.reset();

        // Grab the first element from the queue and try connecting to it.
        // Remove it from the queue before we try to connect, in case the
        // connection attempt fails and calls right back into us to try the next
        // thing.
        SetUpCodePairerParameters params(mDiscoveredParameters.front());
        mDiscoveredParameters.pop_front();

        if (params.mLongDiscriminator)
        {
            auto longDiscriminator = *params.mLongDiscriminator;
            // Look for a matching setup passcode.
            for (auto & payload : mSetupPayloads)
            {
                if (payload.discriminator.MatchesLongDiscriminator(longDiscriminator))
                {
                    params.SetSetupPINCode(payload.setUpPINCode);
                    params.SetSetupDiscriminator(payload.discriminator);
                    mCurrentPASEPayload = payload;
                    break;
                }
            }
            if (!mCurrentPASEPayload)
            {
                ChipLogError(Controller, "SetUpCodePairer: Discovered discriminator %u does not match any of our setup payloads",
                             longDiscriminator);
                // Move on to the the next discovered params; nothing we can do here.
                continue;
            }
        }
        else
        {
            // No discriminator known for this discovered device.  This can work if we have only one
            // setup payload, but otherwise we have no idea what setup passcode to use for it.
            if (mSetupPayloads.size() == 1)
            {
                params.SetSetupPINCode(mSetupPayloads[0].setUpPINCode);
                params.SetSetupDiscriminator(mSetupPayloads[0].discriminator);
                mCurrentPASEPayload = mSetupPayloads[0];
            }
            else
            {
                ChipLogError(Controller,
                             "SetUpCodePairer: Unable to handle discovered parameters with no discriminator, because it has %u "
                             "possible payloads",
                             static_cast<unsigned>(mSetupPayloads.size()));
                continue;
            }
        }

#if CHIP_PROGRESS_LOGGING
        char buf[Transport::PeerAddress::kMaxToStringSize];
        params.GetPeerAddress().ToString(buf);
        ChipLogProgress(Controller, "Attempting PASE connection to %s", buf);
#endif // CHIP_PROGRESS_LOGGING

        // Handle possibly-sync call backs from attempts to establish PASE.
        ExpectPASEEstablishment();

        if (params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
        {
            mCurrentPASEParameters.SetValue(params);
        }

        CHIP_ERROR err;
        if (mConnectionType == SetupCodePairerBehaviour::kCommission)
        {
            err = mCommissioner->PairDevice(mRemoteId, params);
        }
        else
        {
            err = mCommissioner->EstablishPASEConnection(mRemoteId, params);
        }

        LogErrorOnFailure(err);
        if (err == CHIP_NO_ERROR)
        {
            return true;
        }

        // Failed to start establishing PASE.  Move on to the next item.
        mCurrentPASEPayload.reset();
        PASEEstablishmentComplete();
    }

    return false;
}

#if CONFIG_NETWORK_LAYER_BLE
void SetUpCodePairer::OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> matchedLongDiscriminator)
{
    ChipLogProgress(Controller, "Discovered device to be commissioned over BLE");

    mWaitingForDiscovery[kBLETransport] = false;

    // In order to not wait for all the possible addresses discovered over mdns to
    // be tried before trying to connect over BLE, the discovered connection object is
    // inserted at the beginning of the list.
    //
    // It makes it the 'next' thing to try to connect to if there are already some
    // discovered parameters in the list.
    //
    // TODO: Consider implementing the SHOULD the spec has about commissioning things
    // in QR code order by waiting for a second or something before actually starting
    // the first PASE session when we have multiple setup payloads, and sorting the
    // results in setup payload order.  If we do this, we might want to restrict it to
    // cases when the different payloads have different vendor/product IDs, since if
    // they are all the same product presumably ordering really does not matter.
    mDiscoveredParameters.emplace_front(connObj, matchedLongDiscriminator);
    ConnectToDiscoveredDevice();
}

void SetUpCodePairer::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
{
    (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::nullopt);
}

void SetUpCodePairer::OnDiscoveredDeviceWithDiscriminatorOverBleSuccess(void * appState, uint16_t matchedLongDiscriminator,
                                                                        BLE_CONNECTION_OBJECT connObj)
{
    (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::make_optional(matchedLongDiscriminator));
}

void SetUpCodePairer::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
{
    static_cast<SetUpCodePairer *>(appState)->OnBLEDiscoveryError(err);
}

void SetUpCodePairer::OnBLEDiscoveryError(CHIP_ERROR err)
{
    ChipLogError(Controller, "Commissionable node discovery over BLE failed: %" CHIP_ERROR_FORMAT, err.Format());
    mWaitingForDiscovery[kBLETransport] = false;
    LogErrorOnFailure(err);
}
#endif // CONFIG_NETWORK_LAYER_BLE

#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
void SetUpCodePairer::OnDiscoveredDeviceOverWifiPAF()
{
    ChipLogProgress(Controller, "Discovered device to be commissioned over Wi-Fi PAF, RemoteId: %lu", mRemoteId);

    mWaitingForDiscovery[kWiFiPAFTransport] = false;
    auto param                              = SetUpCodePairerParameters();
    param.SetPeerAddress(Transport::PeerAddress(Transport::Type::kWiFiPAF, mRemoteId));
    // TODO: This needs to support concatenated QR codes and set the relevant
    // long discriminator on param.
    //
    // See https://github.com/project-chip/connectedhomeip/issues/39134
    mDiscoveredParameters.emplace_back(param);
    ConnectToDiscoveredDevice();
}

void SetUpCodePairer::OnWifiPAFDiscoveryError(CHIP_ERROR err)
{
    ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed: %" CHIP_ERROR_FORMAT, err.Format());
    mWaitingForDiscovery[kWiFiPAFTransport] = false;
}

void SetUpCodePairer::OnWiFiPAFSubscribeComplete(void * appState)
{
    auto self = reinterpret_cast<SetUpCodePairer *>(appState);
    self->OnDiscoveredDeviceOverWifiPAF();
}

void SetUpCodePairer::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err)
{
    auto self = reinterpret_cast<SetUpCodePairer *>(appState);
    self->OnWifiPAFDiscoveryError(err);
}
#endif

#if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
void SetUpCodePairer::OnTagDiscovered(const chip::Nfc::NFCTag::Identifier & identifier)
{
    ChipLogProgress(Controller, "Discovered device to be commissioned over NFC, Identifier: %u", identifier.discriminator);

    mWaitingForDiscovery[kNFCTransport] = false;
    auto param                          = SetUpCodePairerParameters();
    param.SetPeerAddress(Transport::PeerAddress(Transport::PeerAddress::NFC(identifier.discriminator)));
    // TODO: This needs to support concatenated QR codes and set the relevant
    // long discriminator on param.
    //
    // See https://github.com/project-chip/connectedhomeip/issues/39134
    mDiscoveredParameters.emplace_back(param);
    ConnectToDiscoveredDevice();
}

void SetUpCodePairer::OnTagDiscoveryFailed(CHIP_ERROR error)
{
    ChipLogError(Controller, "Commissionable node discovery over NFC failed: %" CHIP_ERROR_FORMAT, error.Format());
    mWaitingForDiscovery[kNFCTransport] = false;
}
#endif

bool SetUpCodePairer::IdIsPresent(uint16_t vendorOrProductID)
{
    return vendorOrProductID != kNotAvailable;
}

bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & discNodeData) const
{
    if (!discNodeData.Is<Dnssd::CommissionNodeData>())
    {
        return false;
    }

    const Dnssd::CommissionNodeData & nodeData = discNodeData.Get<Dnssd::CommissionNodeData>();

    VerifyOrReturnError(mCommissioner != nullptr, false);
    VerifyOrReturnError(mCommissioner->HasValidCommissioningMode(nodeData), false);

    // Check whether this matches one of our setup payloads.
    for (auto & payload : mSetupPayloads)
    {
        // The advertisement may not include a vendor id, and the payload may not have one either.
        if (IdIsPresent(payload.vendorID) && IdIsPresent(nodeData.vendorId) && payload.vendorID != nodeData.vendorId)
        {
            ChipLogProgress(Controller, "Discovered device vendor ID (%u) does not match our vendor ID (%u).", nodeData.vendorId,
                            payload.vendorID);
            continue;
        }

        // The advertisement may not include a product id, and the payload may not have one either.
        if (IdIsPresent(payload.productID) && IdIsPresent(nodeData.productId) && payload.productID != nodeData.productId)
        {
            ChipLogProgress(Controller, "Discovered device product ID (%u) does not match our product ID (%u).", nodeData.productId,
                            payload.productID);
            continue;
        }

        if (!payload.discriminator.MatchesLongDiscriminator(nodeData.longDiscriminator))
        {
            ChipLogProgress(Controller, "Discovered device discriminator (%u) does not match our discriminator.",
                            nodeData.longDiscriminator);
            continue;
        }

        ChipLogProgress(Controller, "Discovered device with discriminator %u matches one of our setup payloads",
                        nodeData.longDiscriminator);
        return true;
    }

    return false;
}

void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::DiscoveredNodeData & nodeData)
{
    if (!NodeMatchesCurrentFilter(nodeData))
    {
        return;
    }

    ChipLogProgress(Controller, "Discovered device to be commissioned over DNS-SD");

    auto & commissionableNodeData = nodeData.Get<Dnssd::CommissionNodeData>();

    NotifyCommissionableDeviceDiscovered(commissionableNodeData, std::make_optional(commissionableNodeData.longDiscriminator));
}

void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::CommonResolutionData & resolutionData,
                                                           std::optional<uint16_t> matchedLongDiscriminator)
{
    if (mDiscoveryType == DiscoveryType::kDiscoveryNetworkOnlyWithoutPASEAutoRetry)
    {
        // If the discovery type does not want the PASE auto retry mechanism, we will just store
        // a single IP. So the discovery process is stopped as it won't be of any help anymore.
        TEMPORARY_RETURN_IGNORED StopDiscoveryOverDNSSD();
        mDiscoveredParameters.emplace_back(resolutionData, matchedLongDiscriminator, 0);
    }
    else
    {
        for (size_t i = 0; i < resolutionData.numIPs; i++)
        {
            mDiscoveredParameters.emplace_back(resolutionData, matchedLongDiscriminator, i);
        }
    }

    ConnectToDiscoveredDevice();
}

bool SetUpCodePairer::StopPairing(NodeId remoteId)
{
    VerifyOrReturnValue(mRemoteId != kUndefinedNodeId, false);
    VerifyOrReturnValue(remoteId == kUndefinedNodeId || remoteId == mRemoteId, false);

    if (mWaitingForPASE)
    {
        PASEEstablishmentComplete();
    }

    ResetDiscoveryState();
    mRemoteId = kUndefinedNodeId;
    return true;
}

bool SetUpCodePairer::TryNextRendezvousParameters()
{
    if (ConnectToDiscoveredDevice())
    {
        ChipLogProgress(Controller, "Trying connection to commissionee over different transport");
        return true;
    }

    if (DiscoveryInProgress())
    {
        ChipLogProgress(Controller, "Waiting to discover commissionees that match our filters");
        return true;
    }

    return false;
}

bool SetUpCodePairer::DiscoveryInProgress() const
{
    for (const auto & waiting : mWaitingForDiscovery)
    {
        if (waiting)
        {
            return true;
        }
    }

    return false;
}

void SetUpCodePairer::StopAllDiscoveryAttempts()
{
    LogErrorOnFailure(StopDiscoveryOverBLE());
    LogErrorOnFailure(StopDiscoveryOverDNSSD());
    LogErrorOnFailure(StopDiscoveryOverWiFiPAF());
    LogErrorOnFailure(StopDiscoveryOverNFC());

    // Just in case any of those failed to reset the waiting state properly.
    for (auto & waiting : mWaitingForDiscovery)
    {
        waiting = false;
    }
}

void SetUpCodePairer::ResetDiscoveryState()
{
    StopAllDiscoveryAttempts();

    mDiscoveredParameters.clear();
    mCurrentPASEParameters.ClearValue();
    mLastPASEError = CHIP_NO_ERROR;

    mSetupPayloads.clear();

    mSystemLayer->CancelTimer(OnDeviceDiscoveredTimeoutCallback, this);
}

void SetUpCodePairer::ExpectPASEEstablishment()
{
    VerifyOrDie(!mWaitingForPASE);
    mWaitingForPASE = true;
    auto * delegate = mCommissioner->GetPairingDelegate();
    VerifyOrDie(delegate != this);
    mPairingDelegate = delegate;
    mCommissioner->RegisterPairingDelegate(this);
}

void SetUpCodePairer::PASEEstablishmentComplete()
{
    VerifyOrDie(mWaitingForPASE);
    mWaitingForPASE = false;
    mCommissioner->RegisterPairingDelegate(mPairingDelegate);
    mPairingDelegate = nullptr;
}

void SetUpCodePairer::OnStatusUpdate(DevicePairingDelegate::Status status)
{
    if (status == DevicePairingDelegate::Status::SecurePairingFailed)
    {
        // If we're still waiting on discovery, don't propagate this failure
        // (which is due to PASE failure with something we discovered, but the
        // "something" may not have been the right thing) for now.  Wait until
        // discovery completes.  Then we will either succeed and notify
        // accordingly or time out and land in OnStatusUpdate again, but at that
        // point we will not be waiting on discovery anymore.
        if (!mDiscoveredParameters.empty())
        {
            ChipLogProgress(Controller, "Ignoring SecurePairingFailed status for now; we have more discovered devices to try");
            return;
        }

        if (DiscoveryInProgress())
        {
            ChipLogProgress(Controller,
                            "Ignoring SecurePairingFailed status for now; we are waiting to see if we discover more devices");
            return;
        }
    }

    if (mPairingDelegate)
    {
        mPairingDelegate->OnStatusUpdate(status);
    }
}

void SetUpCodePairer::OnPairingComplete(CHIP_ERROR error, const std::optional<RendezvousParameters> & rendezvousParameters,
                                        const std::optional<SetupPayload> & setupPayload)
{
    // Save the pairing delegate so we can notify it.  We want to notify it
    // _after_ we restore the state on the commissioner, in case the delegate
    // ends up immediately calling back into the commissioner again when
    // notified.
    auto * pairingDelegate = mPairingDelegate;
    PASEEstablishmentComplete();

    // Make sure to clear out mCurrentPASEPayload whether we succeeded or failed.
    std::optional<SetupPayload> pasePayload;
    pasePayload.swap(mCurrentPASEPayload);

    if (CHIP_NO_ERROR == error)
    {
        ChipLogProgress(Controller, "PASE session established with commissionee. Stopping discovery.");
        ResetDiscoveryState();
        mRemoteId = kUndefinedNodeId;
        MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
        if (pairingDelegate != nullptr)
        {
            // We don't expect to have a setupPayload passed in here.
            if (setupPayload)
            {
                ChipLogError(Controller,
                             "Unexpected setupPayload passed to SetUpCodePairer::OnPairingComplete.  Where did it come from?");
            }
            pairingDelegate->OnPairingComplete(error, rendezvousParameters, pasePayload);
        }
        return;
    }

    // It may happen that there is a stale DNS entry. If so, ReconfirmRecord will flush
    // the record from the daemon cache once it determines that it is invalid.
    // It may not help for this particular resolve, but may help subsequent resolves.
    if (CHIP_ERROR_TIMEOUT == error && mCurrentPASEParameters.HasValue())
    {
        const auto & params = mCurrentPASEParameters.Value();
        const auto & peer   = params.GetPeerAddress();
        const auto & ip     = peer.GetIPAddress();
        auto err            = Dnssd::Resolver::Instance().ReconfirmRecord(params.mHostName, ip, params.mInterfaceId);
        if (CHIP_NO_ERROR != err && CHIP_ERROR_NOT_IMPLEMENTED != err)
        {
            ChipLogError(Controller, "Error when verifying the validity of an address: %" CHIP_ERROR_FORMAT, err.Format());
        }
    }
    mCurrentPASEParameters.ClearValue();

    // We failed to establish PASE.  Try the next thing we have discovered, if
    // any.
    if (TryNextRendezvousParameters())
    {
        // Keep waiting until that finishes.  Don't call OnPairingComplete yet.
        mLastPASEError = error;
        return;
    }

    MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
    if (pairingDelegate != nullptr)
    {
        pairingDelegate->OnPairingComplete(error, rendezvousParameters, pasePayload);
    }
}

void SetUpCodePairer::OnPairingDeleted(CHIP_ERROR error)
{
    if (mPairingDelegate)
    {
        mPairingDelegate->OnPairingDeleted(error);
    }
}

void SetUpCodePairer::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error)
{
    // Not really expecting this, but handle it anyway.
    if (mPairingDelegate)
    {
        mPairingDelegate->OnCommissioningComplete(deviceId, error);
    }
}

void SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context)
{
    ChipLogError(Controller, "Discovery timed out");
    auto * pairer = static_cast<SetUpCodePairer *>(context);
    pairer->StopAllDiscoveryAttempts();
    if (!pairer->mWaitingForPASE && pairer->mDiscoveredParameters.empty())
    {
        // We're not waiting on any more PASE attempts, and we're not going to
        // discover anything at this point, so we should just notify our
        // listener.
        CHIP_ERROR err = pairer->mLastPASEError;
        if (err == CHIP_NO_ERROR)
        {
            err = CHIP_ERROR_TIMEOUT;
        }
        MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, err);
        pairer->mCommissioner->OnSessionEstablishmentError(err);
    }
}

bool SetUpCodePairer::ShouldDiscoverUsing(RendezvousInformationFlag commissioningChannel) const
{
    for (auto & payload : mSetupPayloads)
    {
        auto & rendezvousInformation = payload.rendezvousInformation;
        if (!rendezvousInformation.HasValue())
        {
            // No idea which commissioning channels this device supports, so we
            // should be trying using all of them.
            return true;
        }

        if (rendezvousInformation.Value().Has(commissioningChannel))
        {
            return true;
        }
    }

    // None of the payloads claimed support for this commissioning channel.
    return false;
}

SetUpCodePairerParameters::SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data,
                                                     std::optional<uint16_t> longDiscriminator, size_t index) :
    mLongDiscriminator(longDiscriminator)
{
    mInterfaceId = data.interfaceId;
    Platform::CopyString(mHostName, data.hostName);

    auto & ip = data.ipAddress[index];
    SetPeerAddress(Transport::PeerAddress::UDP(ip, data.port, ip.IsIPv6LinkLocal() ? data.interfaceId : Inet::InterfaceId::Null()));

    if (data.mrpRetryIntervalIdle.has_value())
    {
        SetIdleInterval(*data.mrpRetryIntervalIdle);
    }

    if (data.mrpRetryIntervalActive.has_value())
    {
        SetActiveInterval(*data.mrpRetryIntervalActive);
    }
}

#if CONFIG_NETWORK_LAYER_BLE
SetUpCodePairerParameters::SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> longDiscriminator,
                                                     bool connected) :
    mLongDiscriminator(longDiscriminator)
{
    Transport::PeerAddress peerAddress = Transport::PeerAddress::BLE();
    SetPeerAddress(peerAddress);
    if (connected)
    {
        SetConnectionObject(connObj);
    }
    else
    {
        SetDiscoveredObject(connObj);
    }
}
#endif // CONFIG_NETWORK_LAYER_BLE

} // namespace Controller
} // namespace chip
