/*
 *
 *    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;

    mCommissioner->StopCommissionableDiscovery();
    return CHIP_NO_ERROR;
}

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
    DeviceLayer::ConnectivityMgr().WiFiPAFCancelIncompleteSubscribe();
#endif
    return CHIP_NO_ERROR;
}

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.
        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
