/*
 *
 *    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_ERROR_NOT_FOUND)
            {
                ChipLogProgress(Controller,
                                "Skipping commissionable node discovery over NFC since no NFC Reader Transport is present");
            }
            else if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller, "Failed to start commissionable node discovery over NFC: %" CHIP_ERROR_FORMAT,
                             err.Format());
            }
        }
        if (ShouldDiscoverUsing(RendezvousInformationFlag::kThread))
        {
            CHIP_ERROR err = StartDiscoveryOverThreadMeshcop();
            if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
            {
                ChipLogProgress(Controller,
                                "Skipping commissionable node discovery over ThreadMeshcop since not supported by the controller!");
            }
            else if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller, "Failed to start commissionable node discovery over ThreadMeshcop: %" 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)
    {
        // No valid NFC reader transport
        return CHIP_ERROR_NOT_FOUND;
    }

    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)
    {
        // No valid NFC reader transport.
        return CHIP_ERROR_NOT_FOUND;
    }

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

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

    if (!mThreadMeshcopCommissionProxy)
    {
        ChipLogError(Controller, "The meshcopCommissioningProxy is not set");
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    if (!mThreadMeshcopCommissionParams.HasValue() ||
        mThreadMeshcopCommissionParams.Value().mBorderAgentAddress.GetTransportType() != Transport::Type::kThreadMeshcop)
    {
        ChipLogError(Controller, "The meshcopCommissioningParams is not set");
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    auto & payload = mSetupPayloads[0];

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

    const SetupDiscriminator connDiscriminator(payload.discriminator);
    Thread::DiscoveryCode code;
    if (connDiscriminator.IsShortDiscriminator())
    {
        code = Thread::DiscoveryCode(connDiscriminator.GetShortValue());
        ChipLogProgress(Controller, "Discovery code from short discriminator: 0x%" PRIx64, code.AsUInt64());
    }
    else
    {
        code = Thread::DiscoveryCode(connDiscriminator.GetLongValue());
        ChipLogProgress(Controller, "Discovery code from long discriminator: 0x%" PRIx64, code.AsUInt64());
    }

    ByteSpan pskc(mThreadMeshcopCommissionParams.Value().mPSKcBuffer);
    {
        mWaitingForDiscovery[kThreadMeshcopTransport] = true;
        Dnssd::DiscoveredNodeData discoveredNodeData;

        CHIP_ERROR err = mThreadMeshcopCommissionProxy->Discover(pskc, mThreadMeshcopCommissionParams.Value().mBorderAgentAddress,
                                                                 code, connDiscriminator, discoveredNodeData, 30);

        mWaitingForDiscovery[kThreadMeshcopTransport] = false;
        ReturnErrorOnFailure(err);
        mCommissioner->OnNodeDiscovered(discoveredNodeData);
        ChipLogProgress(Controller, "Joiner discovered");
    }
    return CHIP_NO_ERROR;
#else
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
#endif // CHIP_SUPPORT_THREAD_MESHCOP
}

CHIP_ERROR SetUpCodePairer::StopDiscoveryOverThreadMeshcop()
{
    // Currently we don't have any methods to stop discovery Over Thread Meshcop.
    // Still return no error here to prevent error logs.
    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.
        mCurrentPASEParameters.ClearValue();
        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);
    StopPairingIfTransportsExhausted(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: %" PRIu64, 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;
    StopPairingIfTransportsExhausted(err);
}

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;
    StopPairingIfTransportsExhausted(error);
}
#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::StopPairingIfTransportsExhausted(CHIP_ERROR err)
{
    if (mWaitingForPASE || !mDiscoveredParameters.empty() || DiscoveryInProgress() || mRemoteId == kUndefinedNodeId)
    {
        return;
    }
    // Clear mRemoteId first to guard against re-entrant calls (e.g. from an async
    // cancel callback fired after StopAllDiscoveryAttempts already cleared the flags).
    mRemoteId          = kUndefinedNodeId;
    CHIP_ERROR failErr = mLastPASEError != CHIP_NO_ERROR ? mLastPASEError : err;
    MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, failErr);
    mCommissioner->OnSessionEstablishmentError(failErr);
}

void SetUpCodePairer::StopAllDiscoveryAttempts()
{
    LogErrorOnFailure(StopDiscoveryOverBLE());
    LogErrorOnFailure(StopDiscoveryOverDNSSD());
    LogErrorOnFailure(StopDiscoveryOverWiFiPAF());
    LogErrorOnFailure(StopDiscoveryOverNFC().NoErrorIf(CHIP_ERROR_NOT_FOUND));
    LogErrorOnFailure(StopDiscoveryOverThreadMeshcop());

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

    // If a PASE attempt is in progress, do not stop physical-proximity
    // transports (BLE, Wi-Fi PAF, NFC) — they have their own completion/timeout
    // mechanisms.  DNS-SD, however, runs indefinitely, so stop it now to
    // prevent DiscoveryInProgress() from being true forever.
    if (pairer->mWaitingForPASE)
    {
        LogErrorOnFailure(pairer->StopDiscoveryOverDNSSD());
        return;
    }

    // No PASE in progress — stop all remaining discovery and fail if nothing is left to try.
    pairer->StopAllDiscoveryAttempts();
    pairer->StopPairingIfTransportsExhausted(CHIP_ERROR_TIMEOUT);
}

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
