/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    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
 *      Declaration of Commissioner Discovery Controller,
 *      a common class that manages state and callbacks
 *      for handling the Commissioner Discovery
 *      and User Directed Commissioning workflow
 *
 */
#include <controller/CommissionerDiscoveryController.h>
#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/AdditionalDataPayloadGenerator.h>

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY

using namespace ::chip;
using namespace chip::Protocols::UserDirectedCommissioning;

void CommissionerDiscoveryController::ResetState()
{
    mCurrentInstance[0] = '\0';
    mVendorId           = 0;
    mProductId          = 0;
    mNodeId             = 0;
    mReady              = true;
}

void CommissionerDiscoveryController::ValidateSession()
{
    if (mReady)
    {
        return;
    }
    if (mUdcServer != nullptr)
    {
        UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
        if (client != nullptr)
        {
            // everything looks good
            return;
        }
    }
    ResetState();
}

void CommissionerDiscoveryController::OnCancel(UDCClientState state)
{
    if (mReady)
    {
        // if state was ready for a new session,
        // then we have lost our discovery controller context and can't perform the commissioning request
        ChipLogDetail(Controller, "CommissionerDiscoveryController::OnCancel received when no current instance.");
        return;
    }

    if (strncmp(mCurrentInstance, state.GetInstanceName(), sizeof(mCurrentInstance)) != 0)
    {
        // if the instance doesn't match the one in our discovery controller context,
        // then we can't perform the commissioning request
        ChipLogDetail(Controller, "CommissionerDiscoveryController::OnCancel received mismatched instance. Current instance=%s",
                      mCurrentInstance);
        return;
    }

    ChipLogDetail(Controller, "------PROMPT USER: %s cancelled commissioning [" ChipLogFormatMEI "," ChipLogFormatMEI ",%s]",
                  state.GetDeviceName(), ChipLogValueMEI(state.GetVendorId()), ChipLogValueMEI(state.GetProductId()),
                  state.GetInstanceName());
    if (mUserPrompter != nullptr)
    {
        mUserPrompter->HidePromptsOnCancel(state.GetVendorId(), state.GetProductId(), state.GetDeviceName());
    }
    return;
}

void CommissionerDiscoveryController::OnCommissionerPasscodeReady(UDCClientState state)
{
    if (mReady)
    {
        // if state was ready for a new session,
        // then we have lost our discovery controller context and can't perform the commissioning request
        ChipLogDetail(Controller,
                      "CommissionerDiscoveryController::OnCommissionerPasscodeReady received when no current instance.");
        return;
    }

    if (strncmp(mCurrentInstance, state.GetInstanceName(), sizeof(mCurrentInstance)) != 0)
    {
        // if the instance doesn't match the one in our discovery controller context,
        // then we can't perform the commissioning request
        ChipLogDetail(
            Controller,
            "CommissionerDiscoveryController::OnCommissionerPasscodeReady received mismatched instance. Current instance=%s",
            mCurrentInstance);
        return;
    }

    if (state.GetCdPort() == 0)
    {
        ChipLogDetail(Controller, "CommissionerDiscoveryController::OnCommissionerPasscodeReady no port");
        return;
    }

    uint32_t passcode = state.GetCachedCommissionerPasscode();
    if (passcode == 0)
    {
        ChipLogError(AppServer, "On UDC: commissioner passcode ready but no passcode");
        CommissionerDeclaration cd;
        cd.SetErrorCode(CommissionerDeclaration::CdError::kUnexpectedCommissionerPasscodeReady);

        if (mUdcServer == nullptr)
        {
            ChipLogError(AppServer, "On UDC: no udc server");
            return;
        }
        mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(state.GetPeerAddress().GetIPAddress(), state.GetCdPort()));
        return;
    }
    else
    {
        // can only get here is ok() has already been called
        ChipLogDetail(AppServer, "On UDC: commissioner passcode ready with passcode - commissioning");

        // start commissioning using the cached passcode
        CommissionWithPasscode(passcode);
        return;
    }
}

void CommissionerDiscoveryController::OnUserDirectedCommissioningRequest(UDCClientState state)
{
    ValidateSession();

    if (!mReady)
    {
        // we must currently have discovery controller context (a UDC prompt under way)
        ChipLogDetail(Controller, "CommissionerDiscoveryController not ready. Current instance=%s", mCurrentInstance);
        return;
    }

    mReady = false;
    Platform::CopyString(mCurrentInstance, state.GetInstanceName());
    mPendingConsent = true;
    char rotatingIdString[Dnssd::kMaxRotatingIdLen * 2 + 1];
    CHIP_ERROR err = Encoding::BytesToUppercaseHexString(state.GetRotatingId(), state.GetRotatingIdLength(), rotatingIdString,
                                                         sizeof(rotatingIdString));
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(AppServer, "On UDC: could not convert rotating id to hex");
        rotatingIdString[0] = '\0';
    }

    ChipLogDetail(Controller,
                  "------PROMPT USER: %s is requesting permission to cast to this TV, approve? [" ChipLogFormatMEI
                  "," ChipLogFormatMEI ",%s,%s]",
                  state.GetDeviceName(), ChipLogValueMEI(state.GetVendorId()), ChipLogValueMEI(state.GetProductId()),
                  state.GetInstanceName(), rotatingIdString);
    if (mUserPrompter != nullptr)
    {
        mUserPrompter->PromptForCommissionOKPermission(state.GetVendorId(), state.GetProductId(), state.GetDeviceName());
    }
    ChipLogDetail(Controller, "------Via Shell Enter: controller ux ok|cancel");
}

/// Callback for getting execution into the main chip thread
void CallbackOk(System::Layer * aSystemLayer, void * aAppState)
{
    ChipLogDetail(AppServer, "UX Ok: now on main thread");
    CommissionerDiscoveryController * cdc = static_cast<CommissionerDiscoveryController *>(aAppState);
    cdc->InternalOk();
}

void CommissionerDiscoveryController::Ok()
{
    ChipLogDetail(AppServer, "UX Ok: moving to main thread");
    assertChipStackLockedByCurrentThread();
    if (CHIP_NO_ERROR != DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(0), CallbackOk, this))
    {
        ChipLogError(AppServer, "UX Ok: StartTimer returned error");
    }
}

void CommissionerDiscoveryController::InternalOk()
{
    ChipLogDetail(AppServer, "UX InternalOk");
    assertChipStackLockedByCurrentThread();
    ValidateSession();

    if (!mPendingConsent)
    {
        ChipLogError(AppServer, "UX InternalOk: no current instance");
        return;
    }
    if (mUdcServer == nullptr)
    {
        ChipLogError(AppServer, "UX InternalOk: no udc server");
        return;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr)
    {
        ChipLogError(AppServer, "UX InternalOk: could not find instance=%s", mCurrentInstance);
        return;
    }

    if (mAppInstallationService == nullptr)
    {
        ChipLogError(AppServer, "UX InternalOk: no app installation service");
        return;
    }

    if (!mAppInstallationService->LookupTargetContentApp(client->GetVendorId(), client->GetProductId()))
    {
        ChipLogDetail(AppServer, "UX InternalOk: app not installed.");

        // notify client that app will be installed
        CommissionerDeclaration cd;
        cd.SetErrorCode(CommissionerDeclaration::CdError::kAppInstallConsentPending);
        mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));

        // dialog
        ChipLogDetail(Controller, "------PROMPT USER: %s is requesting to install app on this TV. vendorId=%d, productId=%d",
                      client->GetDeviceName(), client->GetVendorId(), client->GetProductId());

        if (mUserPrompter != nullptr)
        {
            mUserPrompter->PromptForAppInstallOKPermission(client->GetVendorId(), client->GetProductId(), client->GetDeviceName());
        }
        ChipLogDetail(Controller, "------Via Shell Enter: app install <pid> <vid>");
        return;
    }

    if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kPromptingUser)
    {
        ChipLogError(AppServer, "UX InternalOk: invalid state for ok");
        return;
    }
    client->SetUDCClientProcessingState(UDCClientProcessingState::kObtainingOnboardingPayload);

    if (mPasscodeService == nullptr)
    {
        HandleContentAppPasscodeResponse(0);
        return;
    }

    char rotatingIdBuffer[Dnssd::kMaxRotatingIdLen * 2];
    size_t rotatingIdLength = client->GetRotatingIdLength();
    CHIP_ERROR err =
        Encoding::BytesToUppercaseHexBuffer(client->GetRotatingId(), rotatingIdLength, rotatingIdBuffer, sizeof(rotatingIdBuffer));
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(AppServer, "UX InternalOk: could not convert rotating id to hex");
        return;
    }
    CharSpan rotatingIdSpan(rotatingIdBuffer, 2 * rotatingIdLength);

    uint8_t targetAppCount = client->GetNumTargetAppInfos();

    if (targetAppCount > 0)
    {
        ChipLogDetail(AppServer, "UX InternalOk: checking for each target app specified");

        for (uint8_t i = 0; i < targetAppCount; i++)
        {
            TargetAppInfo info;
            if (client->GetTargetAppInfo(i, info))
            {
                if (mPasscodeService != nullptr)
                {
                    mPasscodeService->LookupTargetContentApp(client->GetVendorId(), client->GetProductId(), rotatingIdSpan, info);
                }
            }
        }
        return;
    }
    ChipLogDetail(AppServer, "UX InternalOk: checking target app associated with client");

    if (mPasscodeService != nullptr)
    {
        mPasscodeService->FetchCommissionPasscodeFromContentApp(client->GetVendorId(), client->GetProductId(), rotatingIdSpan);
    }

    ChipLogDetail(AppServer, "UX Ok: done moving out of main thread");
}

void CommissionerDiscoveryController::HandleTargetContentAppCheck(TargetAppInfo target, uint32_t passcode)
{
    assertChipStackLockedByCurrentThread();
    ValidateSession();

    bool foundTargetApp      = false;
    bool foundPendingTargets = false;

    /**
     * Update our target app list with the status from this target.
     *
     * If we are the first callback to receive a passcode,
     *  then complete commissioning with it.
     * If we are the last expected callback and none has completed commissioning,
     *  then advance to the next step for trying to obtain a passcode.
     * When iterating through the list of targets, keep track of whether any apps have been found,
     *  so that if we advance we can do so with that information (may need to send a CDC).
     */

    if (mUdcServer == nullptr)
    {
        ChipLogError(AppServer, "UX Ok - HandleContentAppCheck: no udc server");
        return;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr)
    {
        ChipLogError(AppServer, "UX Ok - HandleContentAppCheck: could not find instance=%s", mCurrentInstance);
        return;
    }
    if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kObtainingOnboardingPayload)
    {
        ChipLogError(AppServer, "UX Ok - HandleContentAppCheck: invalid state for HandleContentAppPasscodeResponse");
        return;
    }

    uint8_t targetAppCount = client->GetNumTargetAppInfos();
    for (uint8_t i = 0; i < targetAppCount; i++)
    {
        TargetAppInfo info;
        if (client->GetTargetAppInfo(i, info))
        {
            if (info.checkState == TargetAppCheckState::kAppFoundPasscodeReturned)
            {
                // nothing else to do, complete commissioning has been called
                return;
            }
            else if (info.checkState == TargetAppCheckState::kAppFoundNoPasscode)
            {
                foundTargetApp = true;
            }
            else if (info.checkState == TargetAppCheckState::kNotInitialized)
            {
                if (target.vendorId == info.vendorId && target.productId == info.productId)
                {
                    client->SetTargetAppInfoState(i, target.checkState);
                    if (target.checkState != TargetAppCheckState::kAppNotFound)
                    {
                        foundTargetApp = true;
                    }
                }
                else
                {
                    foundPendingTargets = true;
                }
            }
        }
    }
    if (passcode != 0)
    {
        ChipLogDetail(AppServer, "UX Ok - HandleContentAppCheck: found a passcode");
        // we found a passcode and complete commissioning has not been called
        CommissionWithPasscode(passcode);
        return;
    }
    if (foundPendingTargets)
    {
        ChipLogDetail(AppServer, "UX Ok - HandleContentAppCheck: have not heard from all apps");
        // have not heard from all targets so don't do anything
        return;
    }
    if (!foundTargetApp && client->GetNoPasscode())
    {
        // finished iterating through all apps and found none, send CDC
        ChipLogDetail(AppServer, "UX Ok - HandleContentAppCheck: target apps specified but none found, sending CDC");
        CommissionerDeclaration cd;
        cd.SetNoAppsFound(true);
        mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));
    }
    ChipLogDetail(AppServer, "UX Ok - HandleContentAppCheck: advancing");
    // otherwise, advance to the next step for trying to obtain a passcode.
    HandleContentAppPasscodeResponse(0);
    return;
}

/// Callback for getting execution into the main chip thread
void CallbackHandleContentAppPasscodeResponse(System::Layer * aSystemLayer, void * aAppState)
{
    ChipLogDetail(AppServer, "HandleContentAppPasscodeResponse: now on main thread");
    CommissionerDiscoveryController * cdc = static_cast<CommissionerDiscoveryController *>(aAppState);
    cdc->InternalHandleContentAppPasscodeResponse();
}

void CommissionerDiscoveryController::HandleContentAppPasscodeResponse(uint32_t passcode)
{
    assertChipStackLockedByCurrentThread();

    SetPasscode(passcode);
    if (CHIP_NO_ERROR !=
        DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(0), CallbackHandleContentAppPasscodeResponse, this))
    {
        ChipLogError(AppServer, "HandleContentAppPasscodeResponse: StartTimer returned error");
    }
}

void CommissionerDiscoveryController::InternalHandleContentAppPasscodeResponse()
{
    assertChipStackLockedByCurrentThread();
    ValidateSession();
    uint32_t passcode = mPasscode;

    if (mUdcServer == nullptr)
    {
        ChipLogError(AppServer, "UX Ok - HandleContentAppPasscodeResponse: no udc server");
        return;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr)
    {
        ChipLogError(AppServer, "UX Ok - HandleContentAppPasscodeResponse: could not find instance=%s", mCurrentInstance);
        return;
    }
    if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kObtainingOnboardingPayload)
    {
        ChipLogError(AppServer, "UX Ok - HandleContentAppPasscodeResponse: invalid state for HandleContentAppPasscodeResponse");
        return;
    }

    if (mPasscodeService != nullptr)
    {
        // if CommissionerPasscode
        //    - if CommissionerPasscodeReady, then start commissioning
        //    - if CommissionerPasscode, then call new UX method to show passcode, send CDC
        if (passcode == 0 && client->GetCommissionerPasscode() && client->GetCdPort() != 0)
        {
            char rotatingIdBuffer[Dnssd::kMaxRotatingIdLen * 2];
            size_t rotatingIdLength = client->GetRotatingIdLength();
            CHIP_ERROR err = Encoding::BytesToUppercaseHexBuffer(client->GetRotatingId(), rotatingIdLength, rotatingIdBuffer,
                                                                 sizeof(rotatingIdBuffer));
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer, "UX Ok - HandleContentAppPasscodeResponse: could not convert rotating id to hex");
                return;
            }
            CharSpan rotatingIdSpan(rotatingIdBuffer, 2 * rotatingIdLength);

            // first step of commissioner passcode
            ChipLogError(AppServer, "UX Ok: commissioner passcode, sending CDC");
            // generate a passcode
            passcode = mPasscodeService->GetCommissionerPasscode(client->GetVendorId(), client->GetProductId(), rotatingIdSpan);
            if (passcode == 0)
            {
                // passcode feature disabled
                ChipLogError(AppServer, "UX Ok: commissioner passcode disabled, sending CDC with error");
                CommissionerDeclaration cd;
                cd.SetErrorCode(CommissionerDeclaration::CdError::kCommissionerPasscodeDisabled);
                cd.SetNeedsPasscode(true);
                mUdcServer->SendCDCMessage(
                    cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));
                return;
            }
            client->SetCachedCommissionerPasscode(passcode);
            client->SetUDCClientProcessingState(UDCClientProcessingState::kWaitingForCommissionerPasscodeReady);

            CommissionerDeclaration cd;
            cd.SetCommissionerPasscode(true);
            if (mUserPrompter->DisplaysPasscodeAndQRCode())
            {
                cd.SetQRCodeDisplayed(true);
            }
            mUdcServer->SendCDCMessage(cd,
                                       Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));

            // dialog
            ChipLogDetail(Controller,
                          "------PROMPT USER: %s is requesting permission to cast to this TV. Casting passcode: [" ChipLogFormatMEI
                          "]. Additional instructions [" ChipLogFormatMEI "] [%s]. [" ChipLogFormatMEI "," ChipLogFormatMEI ",%s]",
                          client->GetDeviceName(), ChipLogValueMEI(passcode), ChipLogValueMEI(client->GetPairingHint()),
                          client->GetPairingInst(), ChipLogValueMEI(client->GetVendorId()), ChipLogValueMEI(client->GetProductId()),
                          client->GetInstanceName());
            mUserPrompter->PromptWithCommissionerPasscode(client->GetVendorId(), client->GetProductId(), client->GetDeviceName(),
                                                          passcode, client->GetPairingHint(), client->GetPairingInst());
            return;
        }
        if (passcode != 0)
        {
            CommissionWithPasscode(passcode);
            return;
        }
    }

    // if NoPasscode, send CDC
    if (client->GetNoPasscode() && client->GetCdPort() != 0)
    {
        ChipLogDetail(AppServer, "UX Ok: no app passcode and NoPasscode in UDC, sending CDC");
        CommissionerDeclaration cd;
        cd.SetNeedsPasscode(true);
        mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));
        return;
    }

    // if CdUponPasscodeDialog, send CDC
    if (client->GetCdUponPasscodeDialog() && client->GetCdPort() != 0)
    {
        ChipLogDetail(AppServer, "UX Ok: no app passcode and GetCdUponPasscodeDialog in UDC, sending CDC");
        CommissionerDeclaration cd;
        cd.SetNeedsPasscode(true); // TODO: should this be set?
        cd.SetPasscodeDialogDisplayed(true);
        mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));
    }

    ChipLogDetail(Controller, "------PROMPT USER: please enter passcode displayed in casting app ");
    if (mUserPrompter != nullptr)
    {
        mUserPrompter->PromptForCommissionPasscode(client->GetVendorId(), client->GetProductId(), client->GetDeviceName(),
                                                   client->GetPairingHint(), client->GetPairingInst());
    }
    ChipLogDetail(Controller, "------Via Shell Enter: controller ux ok [passcode]");
}

/// Callback for getting execution into the main chip thread
void CallbackCommissionWithPasscode(System::Layer * aSystemLayer, void * aAppState)
{
    ChipLogDetail(AppServer, "CallbackCommissionWithPasscode: now on main thread");
    CommissionerDiscoveryController * cdc = static_cast<CommissionerDiscoveryController *>(aAppState);
    cdc->InternalCommissionWithPasscode();
}

void CommissionerDiscoveryController::CommissionWithPasscode(uint32_t passcode)
{
    assertChipStackLockedByCurrentThread();

    SetPasscode(passcode);
    if (CHIP_NO_ERROR != DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(0), CallbackCommissionWithPasscode, this))
    {
        ChipLogError(AppServer, "CommissionWithPasscode: StartTimer returned error");
    }
}

void CommissionerDiscoveryController::InternalCommissionWithPasscode()
{
    assertChipStackLockedByCurrentThread();
    ValidateSession();
    uint32_t passcode = mPasscode;

    if (!mPendingConsent)
    {
        ChipLogError(AppServer, "UX CommissionWithPasscode: no current instance");
        return;
    }
    if (mUdcServer == nullptr)
    {
        ChipLogError(AppServer, "UX CommissionWithPasscode: no udc server");
        return;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr)
    {
        ChipLogError(AppServer, "UX CommissionWithPasscode: could not find instance=%s", mCurrentInstance);
        return;
    }
    // state needs to be either kPromptingUser or kObtainingOnboardingPayload
    if (!(client->GetUDCClientProcessingState() == UDCClientProcessingState::kPromptingUser ||
          client->GetUDCClientProcessingState() == UDCClientProcessingState::kObtainingOnboardingPayload))
    {
        ChipLogError(AppServer, "UX CommissionWithPasscode: invalid state for CommissionWithPasscode");
        return;
    }
    Transport::PeerAddress peerAddress = client->GetPeerAddress();
    client->SetUDCClientProcessingState(UDCClientProcessingState::kCommissioningNode);
    if (mCommissionerCallback != nullptr)
    {
        if (mUserPrompter != nullptr)
        {
            mUserPrompter->PromptCommissioningStarted(client->GetVendorId(), client->GetProductId(), client->GetDeviceName());
        }
        mCommissionerCallback->ReadyForCommissioning(passcode, client->GetLongDiscriminator(), peerAddress);
    }
}

void CommissionerDiscoveryController::Cancel()
{
    ValidateSession();

    if (!mPendingConsent)
    {
        ChipLogError(AppServer, "UX Cancel: no current instance");
        return;
    }
    if (mUdcServer == nullptr)
    {
        ChipLogError(AppServer, "UX Cancel: no udc server");
        return;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr || client->GetUDCClientProcessingState() != UDCClientProcessingState::kPromptingUser)
    {
        ChipLogError(AppServer, "UX Cancel: invalid state for cancel");
        return;
    }
    client->SetUDCClientProcessingState(UDCClientProcessingState::kUserDeclined);
    mPendingConsent = false;
    ResetState();
}

void CommissionerDiscoveryController::CommissioningSucceeded(uint16_t vendorId, uint16_t productId, NodeId nodeId,
                                                             Messaging::ExchangeManager & exchangeMgr,
                                                             const SessionHandle & sessionHandle)
{
    mVendorId  = vendorId;
    mProductId = productId;
    mNodeId    = nodeId;
    if (mPostCommissioningListener != nullptr)
    {
        ChipLogDetail(Controller, "CommissionerDiscoveryController calling listener");
        mPostCommissioningListener->CommissioningCompleted(vendorId, productId, nodeId, exchangeMgr, sessionHandle);
    }
    else
    {
        PostCommissioningSucceeded();
    }
}

void CommissionerDiscoveryController::CommissioningFailed(CHIP_ERROR error)
{
    if (mUserPrompter != nullptr)
    {
        ChipLogDetail(Controller, "------PROMPT USER: commissioning failed ");
        mUserPrompter->PromptCommissioningFailed(GetCommissioneeName(), error);
    }
    if (mUdcServer == nullptr)
    {
        ChipLogError(AppServer, "UX CommissioningFailed: no udc server");
        return;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr)
    {
        ChipLogError(AppServer, "UX CommissioningFailed: no client");
        return;
    }
    if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kCommissioningNode)
    {
        ChipLogError(AppServer, "UX CommissioningFailed: invalid state");
        return;
    }
    client->SetUDCClientProcessingState(UDCClientProcessingState::kCommissioningFailed);
    client->Reset();

    ResetState();
}

void CommissionerDiscoveryController::PostCommissioningSucceeded()
{
    if (mUserPrompter != nullptr)
    {
        ChipLogDetail(Controller, "------PROMPT USER: commissioning success ");
        mUserPrompter->PromptCommissioningSucceeded(mVendorId, mProductId, GetCommissioneeName());
    }
    ResetState();
}

void CommissionerDiscoveryController::PostCommissioningFailed(CHIP_ERROR error)
{
    if (mUserPrompter != nullptr)
    {
        ChipLogDetail(Controller, "------PROMPT USER: post-commissioning failed ");
        mUserPrompter->PromptCommissioningFailed(GetCommissioneeName(), error);
    }
    ResetState();
}

const char * CommissionerDiscoveryController::GetCommissioneeName()
{
    if (mReady)
    {
        // no current commissionee
        ChipLogError(AppServer, "CommissionerDiscoveryController no current commissionee");
        return nullptr;
    }
    UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
    if (client == nullptr)
    {
        ChipLogError(AppServer, "CommissionerDiscoveryController no UDCState for instance=%s", mCurrentInstance);
        return nullptr;
    }
    return client->GetDeviceName();
}

UDCClientState * CommissionerDiscoveryController::GetUDCClientState()
{
    if (mReady)
    {
        // no current commissionee
        ChipLogError(AppServer, "CommissionerDiscoveryController no current commissionee");
        return nullptr;
    }
    return mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
}

#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
