/*
 *
 *    Copyright (c) 2021 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.
 */

/**
 * @file Contains shell commands for a ContentApp relating to Content App platform of the Video Player.
 */

#include "CastingShellCommands.h"

#include "CastingServer.h"
#include "CastingUtils.h"
#include "app/clusters/bindings/BindingManager.h"
#include <CommissionableInit.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 <platform/CHIPDeviceLayer.h>

using namespace chip;
using namespace chip::DeviceLayer;

namespace {
LinuxCommissionableDataProvider gCommissionableDataProvider;
}

namespace chip {
namespace Shell {

static CHIP_ERROR PrintAllCommands()
{
    streamer_t * sout = 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,
        "  set-fabric <index>        Set current fabric from the casting client's fabric store. Usage: cast set-fabric 1\r\n");
    streamer_printf(sout,
                    "  init <nodeid> <fabric-index>  Initialize casting app using given nodeid and index from previous "
                    "commissioning. Usage: init 18446744004990074879 2\r\n");
    streamer_printf(sout, "  discover             Discover commissioners. Usage: cast discover\r\n");
    streamer_printf(
        sout, "  request <index>      Request commissioning from discovered commissioner with [index]. Usage: cast request 0\r\n");
    streamer_printf(sout, "  launch <url> <display>   Launch content. Usage: cast launch https://www.yahoo.com Hello\r\n");
    streamer_printf(
        sout,
        "  access <node>        Read and display clusters on each endpoint for <node>. Usage: cast access 0xFFFFFFEFFFFFFFFF\r\n");
    streamer_printf(sout, "  sendudc <address> <port> Send UDC message to address. Usage: cast sendudc ::1 5543\r\n");
    streamer_printf(sout, "  udccancel <address> <port> Send UDC cancel message to address. Usage: cast udccancel ::1 5543\r\n");
    streamer_printf(sout,
                    "  udccommissionerpasscode <address> <port> [CommissionerPasscodeReady] [PairingHint] [PairingInst] Send UDC "
                    "commissioner passcode message to address. Usage: udccommissionerpasscode ::1 5543 t 5 HelloWorld\r\n");
    streamer_printf(sout,
                    "  testudc <address> <port> [NoPasscode] [CdUponPasscodeDialog] [vid] [PairingHint] [PairingInst] Send UDC "
                    "message to address. Usage: cast testudc ::1 5543 t t 5 HelloWorld\r\n");
    streamer_printf(
        sout,
        "  cluster [clustercommand] Send cluster command. Usage: cast cluster keypadinput send-key 1 18446744004990074879 1\r\n");
    streamer_printf(sout, "\r\n");

    return CHIP_NO_ERROR;
}

void PrintBindings()
{
    for (const auto & binding : BindingTable::GetInstance())
    {
        ChipLogProgress(NotSpecified,
                        "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.ValueOr(0)));
    }
}

static CHIP_ERROR CastingHandler(int argc, char ** argv)
{
    if (argc == 0 || strcmp(argv[0], "help") == 0)
    {
        return PrintAllCommands();
    }
    if (strcmp(argv[0], "init") == 0)
    {
        ChipLogProgress(DeviceLayer, "init");

        char * eptr;
        chip::NodeId nodeId           = (chip::NodeId) strtoull(argv[1], &eptr, 10);
        chip::FabricIndex fabricIndex = (chip::FabricIndex) strtol(argv[2], &eptr, 10);
        return CastingServer::GetInstance()->TargetVideoPlayerInfoInit(nodeId, fabricIndex, OnConnectionSuccess,
                                                                       OnConnectionFailure, OnNewOrUpdatedEndpoint);
    }
    if (strcmp(argv[0], "discover") == 0)
    {
        ChipLogProgress(DeviceLayer, "discover");

        return DiscoverCommissioners();
    }
    if (strcmp(argv[0], "request") == 0)
    {
        ChipLogProgress(DeviceLayer, "request");
        if (argc < 2)
        {
            return PrintAllCommands();
        }
        char * eptr;
        int index = (int) strtol(argv[1], &eptr, 10);
        return RequestCommissioning(index);
    }
    if (strcmp(argv[0], "setusecommissionerpasscode") == 0)
    {
        ChipLogProgress(DeviceLayer, "setusecommissionerpasscode");
        if (argc < 2)
        {
            return PrintAllCommands();
        }
        char * eptr;
        int useCP = (int) strtol(argv[1], &eptr, 10);
        CastingServer::GetInstance()->SetCommissionerPasscodeEnabled(useCP == 1);
    }
    if (strcmp(argv[0], "launch") == 0)
    {
        ChipLogProgress(DeviceLayer, "launch");
        if (argc < 3)
        {
            return PrintAllCommands();
        }
        char * url     = argv[1];
        char * display = argv[2];
        return CastingServer::GetInstance()->ContentLauncherLaunchURL(
            CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->GetEndpoint(4), url, display, LaunchURLResponseCallback);
    }
    if (strcmp(argv[0], "access") == 0)
    {
        ChipLogProgress(DeviceLayer, "access");
        if (argc < 2)
        {
            return PrintAllCommands();
        }
        char * eptr;
        chip::NodeId node = (chip::NodeId) strtoull(argv[1], &eptr, 0);
        CastingServer::GetInstance()->ReadServerClustersForNode(node);
        return CHIP_NO_ERROR;
    }
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
    if (strcmp(argv[0], "sendudc") == 0)
    {
        char * eptr;
        chip::Inet::IPAddress commissioner;
        chip::Inet::IPAddress::FromString(argv[1], commissioner);
        uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10);
        PrepareForCommissioning();
        return CastingServer::GetInstance()->SendUserDirectedCommissioningRequest(
            chip::Transport::PeerAddress::UDP(commissioner, port));
    }
    if (strcmp(argv[0], "udccancel") == 0)
    {
        char * eptr;
        chip::Inet::IPAddress commissioner;
        chip::Inet::IPAddress::FromString(argv[1], commissioner);
        uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10);

        Protocols::UserDirectedCommissioning::IdentificationDeclaration id;
        id.SetCancelPasscode(true);
        return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port),
                                                                          id);
    }
    if (strcmp(argv[0], "udccommissionerpasscode") == 0)
    {
        char * eptr;
        chip::Inet::IPAddress commissioner;
        chip::Inet::IPAddress::FromString(argv[1], commissioner);
        uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10);

        // udccommissionerpasscode <address> <port> [CommissionerPasscodeReady] [PairingHint] [PairingInst]
        // ex. udccommissionerpasscode <address> <port> t 5 'hello world'

        Protocols::UserDirectedCommissioning::IdentificationDeclaration id;
        id.SetCommissionerPasscode(true);
        id.SetVendorId(1244); // set non-standard vid-pid to prevent dummy content apps from returning a passcode
        id.SetProductId(2234);
        if (argc > 3)
        {
            id.SetCommissionerPasscodeReady(strcmp(argv[3], "t") == 0);
        }
        if (argc > 4)
        {
            uint16_t hint = (uint16_t) strtol(argv[4], &eptr, 10);
            id.SetPairingHint(hint);
        }
        if (argc > 5)
        {
            id.SetPairingInst(argv[5]);
        }
        if (argc > 6)
        {
            uint16_t vid = (uint16_t) strtol(argv[6], &eptr, 10);
            Protocols::UserDirectedCommissioning::TargetAppInfo info;
            info.vendorId = vid;
            id.AddTargetAppInfo(info);
        }
        return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port),
                                                                          id);
    }
    if (strcmp(argv[0], "setcommissionerpasscode") == 0)
    {

        char * eptr;
        uint32_t passcode                                      = (uint32_t) strtol(argv[1], &eptr, 10);
        LinuxDeviceOptions::GetInstance().payload.setUpPINCode = passcode;

        VerifyOrDie(chip::examples::InitCommissionableDataProvider(gCommissionableDataProvider,
                                                                   LinuxDeviceOptions::GetInstance()) == CHIP_NO_ERROR);

        DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider);

        CastingServer::GetInstance()->SetCommissionerPasscodeReady();
    }
    if (strcmp(argv[0], "testudc") == 0)
    {
        char * eptr;
        chip::Inet::IPAddress commissioner;
        chip::Inet::IPAddress::FromString(argv[1], commissioner);
        uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10);

        // sendudc <address> <port> [NoPasscode] [CdUponPasscodeDialog] [vid] [PairingHint] [PairingInst]
        // ex. sendudc <address> <port> t t 111 5 'hello world'

        Protocols::UserDirectedCommissioning::IdentificationDeclaration id;
        if (argc > 3)
        {
            id.SetNoPasscode(strcmp(argv[3], "t") == 0);
        }
        if (argc > 4)
        {
            id.SetCdUponPasscodeDialog(strcmp(argv[4], "t") == 0);
        }
        if (argc > 5)
        {
            uint16_t vid = (uint16_t) strtol(argv[5], &eptr, 10);
            Protocols::UserDirectedCommissioning::TargetAppInfo info;
            info.vendorId = vid;
            id.AddTargetAppInfo(info);
        }
        if (argc > 6)
        {
            uint16_t hint = (uint16_t) strtol(argv[6], &eptr, 10);
            id.SetPairingHint(hint);
        }
        if (argc > 7)
        {
            id.SetPairingInst(argv[7]);
        }
        return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port),
                                                                          id);
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
    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;
    }
    if (strcmp(argv[0], "set-fabric") == 0)
    {
        char * eptr;
        chip::FabricIndex fabricIndex = (chip::FabricIndex) strtol(argv[1], &eptr, 10);
        chip::NodeId nodeId           = CastingServer::GetInstance()->GetVideoPlayerNodeForFabricIndex(fabricIndex);
        if (nodeId == kUndefinedFabricIndex)
        {
            streamer_printf(streamer_get(), "ERROR - invalid fabric or video player nodeId not found\r\n");
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return CastingServer::GetInstance()->TargetVideoPlayerInfoInit(nodeId, fabricIndex, OnConnectionSuccess,
                                                                       OnConnectionFailure, OnNewOrUpdatedEndpoint);
    }
    if (strcmp(argv[0], "cluster") == 0)
    {
        return ProcessClusterCommand(argc, argv);
    }
    return CHIP_ERROR_INVALID_ARGUMENT;
}

void RegisterCastingCommands()
{

    static const shell_command_t sDeviceComand = { &CastingHandler, "cast", "Casting commands. Usage: cast [command_name]" };

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

} // namespace Shell
} // namespace chip
