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

void InvokeContentLauncherPlayPreset(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 playPresetCommand from the contentLauncherCluster
    matter::casting::core::Command<chip::app::Clusters::ContentLauncher::Commands::PlayPreset::Type> * playPresetCommand =
        static_cast<matter::casting::core::Command<chip::app::Clusters::ContentLauncher::Commands::PlayPreset::Type> *>(
            contentLauncherCluster->GetCommand(chip::app::Clusters::ContentLauncher::Commands::PlayPreset::Id));
    VerifyOrReturn(playPresetCommand != nullptr, ChipLogError(AppServer, "PlayPreset command not found on ContentLauncherCluster"));

    // create the PlayPreset request
    chip::app::Clusters::ContentLauncher::Commands::PlayPreset::Type request;
    request.presetID = kPlayPresetId;

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

void ReadContentLauncherMovable(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 movableAttribute from the contentLauncherCluster
    matter::casting::core::Attribute<chip::app::Clusters::ContentLauncher::Attributes::Movable::TypeInfo> * movableAttribute =
        static_cast<matter::casting::core::Attribute<chip::app::Clusters::ContentLauncher::Attributes::Movable::TypeInfo> *>(
            contentLauncherCluster->GetAttribute(chip::app::Clusters::ContentLauncher::Attributes::Movable::Id));
    VerifyOrReturn(movableAttribute != nullptr, ChipLogError(AppServer, "Movable attribute not found on ContentLauncherCluster"));

    // call Read on movableAttribute while passing in success/failure callbacks
    movableAttribute->Read(
        nullptr,
        [](void * context,
           chip::Optional<chip::app::Clusters::ContentLauncher::Attributes::Movable::TypeInfo::DecodableArgType> before,
           chip::app::Clusters::ContentLauncher::Attributes::Movable::TypeInfo::DecodableArgType after) {
            ChipLogProgress(AppServer, "Read Movable value: %d", static_cast<int>(after));
        },
        [](void * context, CHIP_ERROR error) {
            ChipLogError(AppServer, "Movable Read failure with err %" CHIP_ERROR_FORMAT, error.Format());
        });
}

void InvokeMediaFileManagementAddFile(matter::casting::memory::Strong<matter::casting::core::Endpoint> endpoint)
{
    // get mediaFileManagementCluster from the endpoint
    matter::casting::memory::Strong<matter::casting::clusters::media_file_management::MediaFileManagementCluster>
        mediaFileManagementCluster =
            endpoint->GetCluster<matter::casting::clusters::media_file_management::MediaFileManagementCluster>();
    VerifyOrReturn(mediaFileManagementCluster != nullptr);

    // get the addFileCommand from the mediaFileManagementCluster
    matter::casting::core::Command<chip::app::Clusters::MediaFileManagement::Commands::AddFile::Type> * addFileCommand =
        static_cast<matter::casting::core::Command<chip::app::Clusters::MediaFileManagement::Commands::AddFile::Type> *>(
            mediaFileManagementCluster->GetCommand(chip::app::Clusters::MediaFileManagement::Commands::AddFile::Id));
    VerifyOrReturn(addFileCommand != nullptr, ChipLogError(AppServer, "AddFile command not found on MediaFileManagementCluster"));

    // create the AddFile request
    chip::app::Clusters::MediaFileManagement::Commands::AddFile::Type request;
    request.name     = chip::CharSpan::fromCharString(kMediaFileName);
    request.size     = kMediaFileSize;
    request.mimeType = chip::CharSpan::fromCharString(kMediaFileMimeType);
    request.imageUri = chip::CharSpan::fromCharString(kMediaFileImageUri);

    // call Invoke on addFileCommand while passing in success/failure callbacks
    addFileCommand->Invoke(
        request, nullptr,
        [](void * context, const chip::app::Clusters::MediaFileManagement::Commands::AddFile::Type::ResponseType & response) {
            if (response.fileID.IsNull())
            {
                ChipLogProgress(AppServer, "AddFile Success with status: %d (no fileID)", static_cast<int>(response.status));
            }
            else
            {
                ChipLogProgress(AppServer, "AddFile Success with status: %d, fileID: %" PRIu64, static_cast<int>(response.status),
                                response.fileID.Value());
            }
        },
        [](void * context, CHIP_ERROR error) {
            ChipLogError(AppServer, "AddFile Failure with err %" CHIP_ERROR_FORMAT, error.Format());
        },
        chip::MakeOptional(kTimedInvokeCommandTimeoutMs)); // time out after kTimedInvokeCommandTimeoutMs
}

void ReadMediaFileManagementTotalStorage(matter::casting::memory::Strong<matter::casting::core::Endpoint> endpoint)
{
    // get mediaFileManagementCluster from the endpoint
    matter::casting::memory::Strong<matter::casting::clusters::media_file_management::MediaFileManagementCluster>
        mediaFileManagementCluster =
            endpoint->GetCluster<matter::casting::clusters::media_file_management::MediaFileManagementCluster>();
    VerifyOrReturn(mediaFileManagementCluster != nullptr);

    // get the totalStorageAttribute from the mediaFileManagementCluster
    matter::casting::core::Attribute<chip::app::Clusters::MediaFileManagement::Attributes::TotalStorage::TypeInfo> *
        totalStorageAttribute = static_cast<
            matter::casting::core::Attribute<chip::app::Clusters::MediaFileManagement::Attributes::TotalStorage::TypeInfo> *>(
            mediaFileManagementCluster->GetAttribute(chip::app::Clusters::MediaFileManagement::Attributes::TotalStorage::Id));
    VerifyOrReturn(totalStorageAttribute != nullptr,
                   ChipLogError(AppServer, "TotalStorage attribute not found on MediaFileManagementCluster"));

    // call Read on totalStorageAttribute while passing in success/failure callbacks
    totalStorageAttribute->Read(
        nullptr,
        [](void * context,
           chip::Optional<chip::app::Clusters::MediaFileManagement::Attributes::TotalStorage::TypeInfo::DecodableArgType> before,
           chip::app::Clusters::MediaFileManagement::Attributes::TotalStorage::TypeInfo::DecodableArgType after) {
            ChipLogProgress(AppServer, "Read TotalStorage value: %" PRIu64, after);
        },
        [](void * context, CHIP_ERROR error) {
            ChipLogError(AppServer, "TotalStorage Read failure with err %" CHIP_ERROR_FORMAT, error.Format());
        });
}

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

        // demonstrate the new ContentLauncher features (PlayPreset command, Movable attribute)
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling InvokeContentLauncherPlayPreset()");
        InvokeContentLauncherPlayPreset(endpoints[index]);
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling ReadContentLauncherMovable()");
        ReadContentLauncherMovable(endpoints[index]);

        // demonstrate the MediaFileManagement cluster (AddFile command, TotalStorage attribute)
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling InvokeMediaFileManagementAddFile()");
        InvokeMediaFileManagementAddFile(endpoints[index]);
        ChipLogProgress(AppServer, "simple-app-helper.cpp::ConnectionHandler() calling ReadMediaFileManagementTotalStorage()");
        ReadMediaFileManagementTotalStorage(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.
        TEMPORARY_RETURN_IGNORED 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);
        TEMPORARY_RETURN_IGNORED 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::app::Clusters::Binding::Table::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
