/*
 *
 *    Copyright (c) 2023-2024 Project CHIP Authors
 *
 *    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.
 */
#include "simple-app-helper.h"

#include "../tv-casting-common/core/ConnectionCallbacks.h"
#include "clusters/Clusters.h"

#include "app/clusters/bindings/BindingManager.h"
#include <inttypes.h>
#include <lib/core/CHIPCore.h>
#include <lib/shell/Commands.h>
#include <lib/shell/Engine.h>
#include <lib/shell/commands/Help.h>
#include <lib/support/CHIPArgParser.hpp>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/StringBuilder.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/TestOnlyCommissionableDataProvider.h>

// VendorId of the Endpoint on the CastingPlayer that the CastingApp desires to interact with after connection
const uint16_t kDesiredEndpointVendorId    = 65521; // 0xFFF1
const uint16_t kDesiredEndpointVendorIdTwo = 65522; // 0xFFF2
// Indicates that the Commissioner-Generated passcode commissioning flow is in progress.
bool gCommissionerGeneratedPasscodeFlowRunning = false;

DiscoveryDelegateImpl * DiscoveryDelegateImpl::_discoveryDelegateImpl = nullptr;
bool gAwaitingCommissionerPasscodeInput                               = false;
LinuxCommissionableDataProvider gSimpleAppCommissionableDataProvider;
std::shared_ptr<matter::casting::core::CastingPlayer> targetCastingPlayer;

DiscoveryDelegateImpl * DiscoveryDelegateImpl::GetInstance()
{
    if (_discoveryDelegateImpl == nullptr)
    {
        _discoveryDelegateImpl = new DiscoveryDelegateImpl();
    }
    return _discoveryDelegateImpl;
}

void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::Strong<matter::casting::core::CastingPlayer> player)
{
    ChipLogProgress(AppServer, "DiscoveryDelegateImpl::HandleOnAdded()");
    if (commissionersCount == 0)
    {
        ChipLogProgress(AppServer, "---- Awaiting user input ----");
        ChipLogProgress(AppServer, "Select a discovered Casting Player (start index = 0) to request commissioning.");
        ChipLogProgress(
            AppServer,
            "Include the commissioner-generated-passcode flag to attempt the Commissioner-Generated passcode commissioning flow.");
        ChipLogProgress(AppServer, "Example 1 Commissionee Passcode:     cast request 0");
        ChipLogProgress(AppServer, "Example 2 Commissioner Passcode:     cast request 0 commissioner-generated-passcode");
        ChipLogProgress(AppServer, "---- Awaiting user input ----");
    }
    ChipLogProgress(AppServer, "Discovered CastingPlayer #%d", commissionersCount);
    ++commissionersCount;
    player->LogDetail();
}

void DiscoveryDelegateImpl::HandleOnUpdated(matter::casting::memory::Strong<matter::casting::core::CastingPlayer> player)
{
    ChipLogProgress(AppServer, "DiscoveryDelegateImpl::HandleOnUpdated() Updated CastingPlayer with ID: %s", player->GetId());
}

void InvokeContentLauncherLaunchURL(matter::casting::memory::Strong<matter::casting::core::Endpoint> endpoint)
{
    // get contentLauncherCluster from the endpoint
    matter::casting::memory::Strong<matter::casting::clusters::content_launcher::ContentLauncherCluster> contentLauncherCluster =
        endpoint->GetCluster<matter::casting::clusters::content_launcher::ContentLauncherCluster>();
    VerifyOrReturn(contentLauncherCluster != nullptr);

    // get the launchURLCommand from the contentLauncherCluster
    matter::casting::core::Command<chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type> * launchURLCommand =
        static_cast<matter::casting::core::Command<chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type> *>(
            contentLauncherCluster->GetCommand(chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Id));
    VerifyOrReturn(launchURLCommand != nullptr, ChipLogError(AppServer, "LaunchURL command not found on ContentLauncherCluster"));

    // create the LaunchURL request
    chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type request;
    request.contentURL    = chip::CharSpan::fromCharString(kContentURL);
    request.displayString = chip::Optional<chip::CharSpan>(chip::CharSpan::fromCharString(kContentDisplayStr));
    request.brandingInformation =
        chip::MakeOptional(chip::app::Clusters::ContentLauncher::Structs::BrandingInformationStruct::Type());

    // call Invoke on launchURLCommand while passing in success/failure callbacks
    launchURLCommand->Invoke(
        request, nullptr,
        [](void * context, const chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type::ResponseType & response) {
            ChipLogProgress(AppServer, "LaunchURL Success with response.data: %s",
                            chip::NullTerminated(response.data.Value()).c_str());
        },
        [](void * context, CHIP_ERROR error) {
            ChipLogError(AppServer, "LaunchURL Failure with err %" CHIP_ERROR_FORMAT, error.Format());
        },
        chip::MakeOptional(kTimedInvokeCommandTimeoutMs)); // time out after kTimedInvokeCommandTimeoutMs
}

void ReadApplicationBasicVendorID(matter::casting::memory::Strong<matter::casting::core::Endpoint> endpoint)
{
    // get applicationBasicCluster from the endpoint
    matter::casting::memory::Strong<matter::casting::clusters::application_basic::ApplicationBasicCluster> applicationBasicCluster =
        endpoint->GetCluster<matter::casting::clusters::application_basic::ApplicationBasicCluster>();
    VerifyOrReturn(applicationBasicCluster != nullptr);

    // get the vendorIDAttribute from the applicationBasicCluster
    matter::casting::core::Attribute<chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo> * vendorIDAttribute =
        static_cast<matter::casting::core::Attribute<chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo> *>(
            applicationBasicCluster->GetAttribute(chip::app::Clusters::ApplicationBasic::Attributes::VendorID::Id));
    VerifyOrReturn(vendorIDAttribute != nullptr,
                   ChipLogError(AppServer, "VendorID attribute not found on ApplicationBasicCluster"));

    // call Read on vendorIDAttribute while passing in success/failure callbacks
    vendorIDAttribute->Read(
        nullptr,
        [](void * context,
           chip::Optional<chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo::DecodableArgType> before,
           chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo::DecodableArgType after) {
            if (before.HasValue())
            {
                ChipLogProgress(AppServer, "Read VendorID value: %d [Before reading value: %d]", after, before.Value());
            }
            else
            {
                ChipLogProgress(AppServer, "Read VendorID value: %d", after);
            }
        },
        [](void * context, CHIP_ERROR error) {
            ChipLogError(AppServer, "VendorID Read failure with err %" CHIP_ERROR_FORMAT, error.Format());
        });
}

void SubscribeToMediaPlaybackCurrentState(matter::casting::memory::Strong<matter::casting::core::Endpoint> endpoint)
{
    // get mediaPlaybackCluster from the endpoint
    matter::casting::memory::Strong<matter::casting::clusters::media_playback::MediaPlaybackCluster> mediaPlaybackCluster =
        endpoint->GetCluster<matter::casting::clusters::media_playback::MediaPlaybackCluster>();
    VerifyOrReturn(mediaPlaybackCluster != nullptr);

    // get the currentStateAttribute from the applicationBasicCluster
    matter::casting::core::Attribute<chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo> *
        currentStateAttribute =
            static_cast<matter::casting::core::Attribute<chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo> *>(
                mediaPlaybackCluster->GetAttribute(chip::app::Clusters::MediaPlayback::Attributes::CurrentState::Id));
    VerifyOrReturn(currentStateAttribute != nullptr,
                   ChipLogError(AppServer, "CurrentState attribute not found on MediaPlaybackCluster"));

    // call Subscribe on currentStateAttribute while passing in success/failure callbacks
    currentStateAttribute->Subscribe(
        nullptr,
        [](void * context,
           chip::Optional<chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType> before,
           chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType after) {
            if (before.HasValue())
            {
                ChipLogProgress(AppServer, "Read CurrentState value: %d [Before reading value: %d]", static_cast<int>(after),
                                static_cast<int>(before.Value()));
            }
            else
            {
                ChipLogProgress(AppServer, "Read CurrentState value: %d", static_cast<int>(after));
            }
        },
        [](void * context, CHIP_ERROR error) {
            ChipLogError(AppServer, "CurrentState Read failure with err %" CHIP_ERROR_FORMAT, error.Format());
        },
        kMinIntervalFloorSeconds, kMaxIntervalCeilingSeconds);
}

CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options)
{
    ChipLogProgress(Discovery, "InitCommissionableDataProvider()");
    chip::Optional<uint32_t> setupPasscode;

    if (options.payload.setUpPINCode != 0)
    {
        setupPasscode.SetValue(options.payload.setUpPINCode);
        ChipLogProgress(Discovery, "InitCommissionableDataProvider() using setupPasscode: %d", setupPasscode.Value());
    }
    else if (!options.spake2pVerifier.HasValue())
    {
        uint32_t defaultTestPasscode = 0;
        chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider;
        VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR);

        ChipLogError(Support,
                     "InitCommissionableDataProvider() *** WARNING: Using temporary passcode %u due to no neither --passcode or "
                     "--spake2p-verifier-base64 "
                     "given on command line. This is temporary and will be deprecated. Please update your scripts "
                     "to explicitly configure onboarding credentials. ***",
                     static_cast<unsigned>(defaultTestPasscode));
        setupPasscode.SetValue(defaultTestPasscode);
        options.payload.setUpPINCode = defaultTestPasscode;
    }
    else
    {
        ChipLogError(Support,
                     "InitCommissionableDataProvider() *** WARNING: Passcode is 0, so will be ignored, and verifier will take "
                     "over. Onboarding payload printed for debug will be invalid, but if the onboarding payload had been given "
                     "properly to the commissioner later, PASE will succeed. ***");
    }

    // Default to the minimum PBKDF iterations (1,000) for this example implementation. For TV devices and TV casting app production
    // implementations, you should use a higher number of PBKDF iterations to enhance security. The default minimum iterations are
    // not sufficient against brute-force and rainbow table attacks. Increasing the number of iterations will increase the
    // computational time required to derive the key. This can slow down the authentication process, especially on devices with
    // limited processing power like a Raspberry Pi 4. For a production implementation, you should measure the actual performance on
    // the target device.
    uint32_t spake2pIterationCount =
        chip::Crypto::kSpake2p_Min_PBKDF_Iterations; // 1,000 - Hypothetical key derivation time: ~20 milliseconds (ms).
    // uint32_t spake2pIterationCount = chip::Crypto::kSpake2p_Max_PBKDF_Iterations; // 100,000 - Hypothetical key derivation time:
    // ~2 seconds.
    if (options.spake2pIterations == 1000)
    {
        spake2pIterationCount = options.spake2pIterations;
        ChipLogError(Support,
                     "InitCommissionableDataProvider() *** WARNING: PASE PBKDF iterations provided are the minimum allowable: %u. "
                     "Increase for production use to enhance security. ***",
                     static_cast<unsigned>(spake2pIterationCount));
    }
    else if ((options.spake2pIterations > 1000))
    {
        spake2pIterationCount = options.spake2pIterations;
        ChipLogProgress(Support, "InitCommissionableDataProvider() PASE PBKDF iterations set to: %u.",
                        static_cast<unsigned>(spake2pIterationCount));
    }
    else
    {
        ChipLogError(Support,
                     "InitCommissionableDataProvider() *** WARNING: PASE PBKDF iterations set to the minimum allowable: %u. "
                     "Increase for production use to enhance security. ***",
                     static_cast<unsigned>(spake2pIterationCount));
    }

    return provider.Init(options.spake2pVerifier, options.spake2pSalt, spake2pIterationCount, setupPasscode,
                         options.payload.discriminator.GetLongValue());
}

void LogEndpointsDetails(const std::vector<matter::casting::memory::Strong<matter::casting::core::Endpoint>> & endpoints)
{
    ChipLogProgress(AppServer, "simple-app-helper.cpp::LogEndpointsDetails() Number of Endpoints: %d",
                    static_cast<int>(endpoints.size()));
    for (const auto & endpoint : endpoints)
    {
        endpoint->LogDetail();
    }
}

void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer)
{
    ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler()");

    // For a connection failure, called back with an error and nullptr.
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(AppServer,
                                "simple-app-helper.cpp::ConnectionHandler(): Failed to connect to CastingPlayer (ID: %s, Vendor "
                                "ID: %d) with err %" CHIP_ERROR_FORMAT,
                                targetCastingPlayer->GetId(), targetCastingPlayer->GetVendorId(), err.Format()));

    ChipLogProgress(AppServer,
                    "simple-app-helper.cpp::ConnectionHandler(): Successfully connected to CastingPlayer (ID: %s, Vendor ID: %d)",
                    castingPlayer->GetId(), targetCastingPlayer->GetVendorId());
    ChipLogProgress(
        AppServer,
        "simple-app-helper.cpp::ConnectionHandler(): Demo interactions, getting endpoints matching Endpoint Vendor ID: %d",
        kDesiredEndpointVendorId);
    std::vector<matter::casting::memory::Strong<matter::casting::core::Endpoint>> endpoints = castingPlayer->GetEndpoints();
    LogEndpointsDetails(endpoints);

    // Find the desired Endpoint and auto-trigger some Matter Casting demo interactions
    auto it = std::find_if(endpoints.begin(), endpoints.end(),
                           [](const matter::casting::memory::Strong<matter::casting::core::Endpoint> & endpoint) {
                               return endpoint->GetVendorId() == kDesiredEndpointVendorId;
                           });
    if (it != endpoints.end())
    {
        // The desired endpoint is endpoints[index]
        unsigned index = (unsigned int) std::distance(endpoints.begin(), it);

        ChipLogProgress(
            AppServer,
            "simple-app-helper.cpp::ConnectionHandler(): Triggering demo interactions with CastingPlayer (ID: %s). Endpoint ID: %d",
            castingPlayer->GetId(), endpoints[index]->GetId());

        // demonstrate invoking a command
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling InvokeContentLauncherLaunchURL()");
        InvokeContentLauncherLaunchURL(endpoints[index]);

        // demonstrate reading an attribute
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling ReadApplicationBasicVendorID()");
        ReadApplicationBasicVendorID(endpoints[index]);

        // demonstrate subscribing to an attribute
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling SubscribeToMediaPlaybackCurrentState()");
        SubscribeToMediaPlaybackCurrentState(endpoints[index]);
    }
    else
    {
        ChipLogError(
            AppServer,
            "simple-app-helper.cpp::ConnectionHandler():Desired Endpoint Vendor ID not found on the CastingPlayer (ID: %s)",
            castingPlayer->GetId());
    }
}

void CommissionerDeclarationCallback(const chip::Transport::PeerAddress & source,
                                     chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd)
{
    ChipLogProgress(AppServer,
                    "simple-app-helper.cpp::CommissionerDeclarationCallback() called with CommissionerDeclaration message:");
    cd.DebugLog();
    if (cd.GetCommissionerPasscode())
    {
        ChipLogProgress(AppServer, "---- Awaiting user input ----");
        ChipLogProgress(AppServer, "Input the Commissioner-Generated passcode displayed on the CastingPlayer UX.");
        ChipLogProgress(AppServer, "Input 12345678 to use the default passcode.");
        ChipLogProgress(AppServer, "Example:     cast setcommissionerpasscode 12345678");
        ChipLogProgress(AppServer, "---- Awaiting user input ----");
        gAwaitingCommissionerPasscodeInput = true;
    }
}

#if defined(ENABLE_CHIP_SHELL)
void RegisterCommands()
{
    static const chip::Shell::shell_command_t sDeviceComand = { &CommandHandler, "cast",
                                                                "Casting commands. Usage: cast [command_name]" };

    // Register the root `device` command with the top-level shell.
    chip::Shell::Engine::Root().RegisterCommands(&sDeviceComand, 1);
}

CHIP_ERROR CommandHandler(int argc, char ** argv)
{
    if (argc == 0 || strcmp(argv[0], "help") == 0)
    {
        return PrintAllCommands();
    }
    if (strcmp(argv[0], "discover") == 0)
    {
        ChipLogProgress(AppServer, "CommandHandler() discover");

        return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType);
    }
    if (strcmp(argv[0], "stop-discovery") == 0)
    {
        ChipLogProgress(AppServer, "CommandHandler() stop-discovery");
        return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StopDiscovery();
    }
    if (strcmp(argv[0], "request") == 0)
    {
        ChipLogProgress(AppServer, "CommandHandler() request");
        if (argc < 2)
        {
            return PrintAllCommands();
        }
        char * eptr;
        unsigned long index = static_cast<unsigned long>(strtol(argv[1], &eptr, 10));
        std::vector<matter::casting::memory::Strong<matter::casting::core::CastingPlayer>> castingPlayers =
            matter::casting::core::CastingPlayerDiscovery::GetInstance()->GetCastingPlayers();
        VerifyOrReturnValue(index < castingPlayers.size(), CHIP_ERROR_INVALID_ARGUMENT,
                            ChipLogError(AppServer, "Invalid casting player index provided: %lu", index));
        targetCastingPlayer = castingPlayers.at(index);

        gCommissionerGeneratedPasscodeFlowRunning = false;

        // Specify the TargetApp that the client wants to interact with after commissioning. If this value is passed in,
        // VerifyOrEstablishConnection() will force UDC, in case the desired TargetApp is not found in the on-device
        // CastingStore
        matter::casting::core::IdentificationDeclarationOptions idOptions;
        chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo;
        targetAppInfo.vendorId = kDesiredEndpointVendorId;
        // For demonstration purposes add another TargetApp Vendor ID to interact with after commissioning. If the
        // target content app's allowedVendorList contains the casting client's Vendor ID, then the client will receive
        // the corresponding bindings and endpoints.
        chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfoTwo;
        targetAppInfoTwo.vendorId = kDesiredEndpointVendorIdTwo;

        if (argc == 3)
        {

            if (strcmp(argv[2], "commissioner-generated-passcode") == 0)
            {
                // Attempt Commissioner-Generated Passcode (commissioner-generated-passcode) commissioning flow only if the
                // CastingPlayer indicates support for it.
                if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode())
                {
                    ChipLogProgress(AppServer,
                                    "CommandHandler() request %lu commissioner-generated-passcode. Attempting the "
                                    "Commissioner-Generated Passcode commissioning flow",
                                    index);
                    idOptions.mCommissionerPasscode           = true;
                    gCommissionerGeneratedPasscodeFlowRunning = true;
                }
                else
                {
                    ChipLogError(AppServer,
                                 "CommandHandler() request %lu commissioner-generated-passcode. Selected CastingPLayer does not "
                                 "support the Commissioner-Generated Passcode commissioning flow",
                                 index);
                }
            }
        }

        CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo);
        if (result != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "CommandHandler() request, failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format());
        }
        result = CHIP_NO_ERROR;
        result = idOptions.addTargetAppInfo(targetAppInfoTwo);
        if (result != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "CommandHandler() request, failed to add targetAppInfoTwo: %" CHIP_ERROR_FORMAT,
                         result.Format());
        }

        if (!gCommissionerGeneratedPasscodeFlowRunning)
        {
            uint32_t defaultTestPasscode = 0;
            chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider;
            VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR);
            ChipLogProgress(AppServer, "CommandHandler() request, tv-casting-app Commissionee Passcode: %u",
                            static_cast<unsigned>(defaultTestPasscode));
        }

        matter::casting::core::ConnectionCallbacks connectionCallbacks;
        connectionCallbacks.mOnConnectionComplete = ConnectionHandler;
        // Provide an handler (Optional) for Commissioner's CommissionerDeclaration messages. The CommissionerDeclaration messages
        // provide information indicating the Commissioner's pre-commissioning state.
        connectionCallbacks.mCommissionerDeclarationCallback = CommissionerDeclarationCallback;

        targetCastingPlayer->VerifyOrEstablishConnection(connectionCallbacks, matter::casting::core::kCommissioningWindowTimeoutSec,
                                                         idOptions);
        ChipLogProgress(AppServer, "CommandHandler() request, VerifyOrEstablishConnection() called, calling StopDiscovery()");
        // Stop discovery since we have discovered, and are now connecting to the desired CastingPlayer.
        matter::casting::core::CastingPlayerDiscovery::GetInstance()->StopDiscovery();
        return CHIP_NO_ERROR;
    }
    if (strcmp(argv[0], "setcommissionerpasscode") == 0)
    {
        ChipLogProgress(AppServer, "CommandHandler() setcommissionerpasscode");
        if (argc < 2)
        {
            return PrintAllCommands();
        }
        char * eptr;
        uint32_t userEnteredPasscode = (uint32_t) strtol(argv[1], &eptr, 10);
        if (gAwaitingCommissionerPasscodeInput)
        {
            ChipLogProgress(AppServer, "CommandHandler() setcommissionerpasscode user-entered passcode: %d", userEnteredPasscode);
            gAwaitingCommissionerPasscodeInput = false;

            // Per connectedhomeip/examples/platform/linux/LinuxCommissionableDataProvider.h: We don't support overriding the
            // passcode post-init (it is deprecated!). Therefore we need to initiate a new provider with the user-entered
            // Commissioner-generated passcode, and then update the CastigApp's AppParameters to update the commissioning session's
            // passcode.
            LinuxDeviceOptions::GetInstance().payload.setUpPINCode = userEnteredPasscode;
            CHIP_ERROR err                                         = CHIP_NO_ERROR;
            err = InitCommissionableDataProvider(gSimpleAppCommissionableDataProvider, LinuxDeviceOptions::GetInstance());
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer,
                             "CommandHandler() setcommissionerpasscode InitCommissionableDataProvider() err %" CHIP_ERROR_FORMAT,
                             err.Format());
                return err;
            }
            // Update the CommissionableDataProvider stored in this CastingApp's AppParameters and the CommissionableDataProvider to
            // be used for the commissioning session.
            err = matter::casting::core::CastingApp::GetInstance()->UpdateCommissionableDataProvider(
                &gSimpleAppCommissionableDataProvider);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer,
                             "CommandHandler() setcommissionerpasscode InitCommissionableDataProvider() err %" CHIP_ERROR_FORMAT,
                             err.Format());
                return err;
            }

            // Continue Connecting to the target CastingPlayer with the user entered Commissioner-generated Passcode.
            err = targetCastingPlayer->ContinueConnecting();
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer,
                             "CommandHandler() setcommissionerpasscode ContinueConnecting() failed due to err %" CHIP_ERROR_FORMAT,
                             err.Format());
                // Since continueConnecting() failed, Attempt to cancel the connection attempt with
                // the CastingPlayer/Commissioner by calling StopConnecting().
                err = targetCastingPlayer->StopConnecting();
                if (err != CHIP_NO_ERROR)
                {
                    ChipLogError(AppServer,
                                 "CommandHandler() setcommissionerpasscode, ContinueConnecting() failed and then StopConnecting "
                                 "failed due to err %" CHIP_ERROR_FORMAT,
                                 err.Format());
                }
                return err;
            }
        }
        else
        {
            ChipLogError(
                AppServer,
                "CommandHandler() setcommissionerpasscode, no Commissioner-Generated passcode input expected at this time.");
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
    }
    if (strcmp(argv[0], "stop-connecting") == 0)
    {
        ChipLogProgress(AppServer, "CommandHandler() stop-connecting");
        CHIP_ERROR err = targetCastingPlayer->StopConnecting();
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "CommandHandler() stop-connecting, err %" CHIP_ERROR_FORMAT, err.Format());
            return err;
        }
    }
    if (strcmp(argv[0], "print-bindings") == 0)
    {
        PrintBindings();
        return CHIP_NO_ERROR;
    }
    if (strcmp(argv[0], "print-fabrics") == 0)
    {
        PrintFabrics();
        return CHIP_NO_ERROR;
    }
    if (strcmp(argv[0], "delete-fabric") == 0)
    {
        char * eptr;
        chip::FabricIndex fabricIndex = (chip::FabricIndex) strtol(argv[1], &eptr, 10);
        chip::Server::GetInstance().GetFabricTable().Delete(fabricIndex);
        return CHIP_NO_ERROR;
    }
    return CHIP_ERROR_INVALID_ARGUMENT;
}

CHIP_ERROR PrintAllCommands()
{
    chip::Shell::streamer_t * sout = chip::Shell::streamer_get();
    streamer_printf(sout, "  help                 Usage: cast <subcommand>\r\n");
    streamer_printf(sout, "  print-bindings       Usage: cast print-bindings\r\n");
    streamer_printf(sout, "  print-fabrics        Usage: cast print-fabrics\r\n");
    streamer_printf(
        sout,
        "  delete-fabric <index>     Delete a fabric from the casting client's fabric store. Usage: cast delete-fabric 1\r\n");
    streamer_printf(sout, "  discover             Discover Casting Players. Usage: cast discover\r\n");
    streamer_printf(sout, "  stop-discovery       Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n");
    streamer_printf(sout,
                    "  request <index>                                  Request connecting to discovered Casting Player with "
                    "[index] using the Commissionee-Generated passcode commissioning flow. Usage: cast request 0\r\n");
    streamer_printf(sout,
                    "  request <index> commissioner-generated-passcode  Request connecting to discovered Casting Player with "
                    "[index] using the Commissioner-Generated passcode commissioning flow. Usage: cast request 0 "
                    "commissioner-generated-passcode\r\n");
    streamer_printf(sout,
                    "  setcommissionerpasscode <passcode>               Set the commissioning session's passcode to the "
                    "Commissioner-Generated passcode. Used for the the Commissioner-Generated passcode commissioning flow. Usage: "
                    "cast setcommissionerpasscode 12345678\r\n");
    streamer_printf(sout,
                    "  stop-connecting                                  Stop connecting to Casting Player upon "
                    "Commissioner-Generated passcode commissioning flow passcode input request. Usage: cast stop-connecting\r\n");
    streamer_printf(sout, "\r\n");

    return CHIP_NO_ERROR;
}

void PrintBindings()
{
    for (const auto & binding : chip::BindingTable::GetInstance())
    {
        ChipLogProgress(AppServer,
                        "PrintBindings() Binding type=%d fab=%d nodeId=0x" ChipLogFormatX64
                        " groupId=%d local endpoint=%d remote endpoint=%d cluster=" ChipLogFormatMEI,
                        binding.type, binding.fabricIndex, ChipLogValueX64(binding.nodeId), binding.groupId, binding.local,
                        binding.remote, ChipLogValueMEI(binding.clusterId.value_or(0)));
    }
}

void PrintFabrics()
{
    // set fabric to be the first in the list
    for (const auto & fb : chip::Server::GetInstance().GetFabricTable())
    {
        chip::FabricIndex fabricIndex = fb.GetFabricIndex();
        ChipLogError(AppServer, "Next Fabric index=%d", fabricIndex);
        if (!fb.IsInitialized())
        {
            ChipLogError(AppServer, " -- Not initialized");
            continue;
        }
        chip::NodeId myNodeId = fb.GetNodeId();
        ChipLogProgress(AppServer,
                        "---- Current Fabric nodeId=0x" ChipLogFormatX64 " fabricId=0x" ChipLogFormatX64 " fabricIndex=%d",
                        ChipLogValueX64(myNodeId), ChipLogValueX64(fb.GetFabricId()), fabricIndex);
    }
}

#endif // ENABLE_CHIP_SHELL
