/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "CastingUtils.h"

#include "CommissioningCallbacks.h"

using namespace chip;
using namespace chip::System;
using namespace chip::DeviceLayer;
using namespace chip::Dnssd;

// TODO: Accept these values over CLI
const char * kContentUrl        = "https://www.test.com/videoid";
const char * kContentDisplayStr = "Test video";
int gInitialContextVal          = 121212;

CHIP_ERROR DiscoverCommissioners()
{
    // Send discover commissioners request
    ReturnErrorOnFailure(CastingServer::GetInstance()->DiscoverCommissioners());

    // Give commissioners some time to respond and then ScheduleWork to initiate commissioning
    return DeviceLayer::SystemLayer().StartTimer(
        chip::System::Clock::Milliseconds32(kCommissionerDiscoveryTimeoutInMs),
        [](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(InitCommissioningFlow); }, nullptr);
}

CHIP_ERROR RequestCommissioning(int index)
{
    chip::Optional<TargetVideoPlayerInfo *> associatedConnectableVideoPlayer;
    const Dnssd::DiscoveredNodeData * selectedCommissioner =
        CastingServer::GetInstance()->GetDiscoveredCommissioner(index, associatedConnectableVideoPlayer);
    if (selectedCommissioner == nullptr)
    {
        ChipLogError(AppServer, "No such commissioner with index %d exists", index);
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    PrepareForCommissioning(selectedCommissioner);
    return CHIP_NO_ERROR;
}

/**
 * Enters commissioning mode, opens commissioning window, logs onboarding payload.
 * If non-null selectedCommissioner is provided, sends user directed commissioning
 * request to the selectedCommissioner and advertises self as commissionable node over DNS-SD
 */
void PrepareForCommissioning(const Dnssd::DiscoveredNodeData * selectedCommissioner)
{
    CastingServer::GetInstance()->Init();

    CommissioningCallbacks commissioningCallbacks;
    commissioningCallbacks.commissioningComplete = HandleCommissioningCompleteCallback;
    CastingServer::GetInstance()->OpenBasicCommissioningWindow(commissioningCallbacks, OnConnectionSuccess, OnConnectionFailure,
                                                               OnNewOrUpdatedEndpoint);

    // Display onboarding payload
    chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig();

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
    if (selectedCommissioner != nullptr)
    {
        // Send User Directed commissioning request
        // Wait 1 second to allow our commissionee DNS records to publish (needed on Mac)
        int32_t expiration = 1;
        ReturnOnFailure(DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(expiration), HandleUDCSendExpiration,
                                                              (void *) selectedCommissioner));
    }
    else
    {
        ChipLogProgress(AppServer, "To run discovery again, enter: cast discover");
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
}

void InitCommissioningFlow(intptr_t commandArg)
{
    int commissionerCount = 0;

    // Display discovered commissioner TVs to ask user to select one
    for (int i = 0; i < CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES; i++)
    {
        chip::Optional<TargetVideoPlayerInfo *> associatedConnectableVideoPlayer;
        const Dnssd::DiscoveredNodeData * commissioner =
            CastingServer::GetInstance()->GetDiscoveredCommissioner(i, associatedConnectableVideoPlayer);
        if (commissioner != nullptr)
        {
            ChipLogProgress(AppServer, "Discovered Commissioner #%d", commissionerCount);
            commissionerCount++;
            commissioner->LogDetail();
            if (associatedConnectableVideoPlayer.HasValue())
            {
                TargetVideoPlayerInfo * targetVideoPlayerInfo = associatedConnectableVideoPlayer.Value();
                ChipLogProgress(AppServer, "Previously connected with nodeId 0x" ChipLogFormatX64 " fabricIndex: %d",
                                ChipLogValueX64(targetVideoPlayerInfo->GetNodeId()), targetVideoPlayerInfo->GetFabricIndex());
            }
        }
    }

    if (commissionerCount > 0)
    {
        ChipLogProgress(AppServer, "%d commissioner(s) discovered. Select one (by number# above) to request commissioning from: ",
                        commissionerCount);

        ChipLogProgress(AppServer, "Example: cast request 0");
    }
    else
    {
        ChipLogError(AppServer, "No commissioner discovered, commissioning must be initiated manually!");
        PrepareForCommissioning();
    }
}

void LaunchURLResponseCallback(CHIP_ERROR err)
{
    ChipLogProgress(AppServer, "LaunchURLResponseCallback called with %" CHIP_ERROR_FORMAT, err.Format());
}

void OnCurrentStateReadResponseSuccess(
    void * context, chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType responseData)
{
    ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess called with responseData: %d", static_cast<int>(responseData));
    switch (responseData)
    {
    case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kPlaying:
        ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Playing");
        break;
    case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kPaused:
        ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Paused");
        break;
    case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kNotPlaying:
        ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Not Playing");
        break;
    case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kBuffering:
        ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Buffering");
        break;
    default:
        ChipLogError(AppServer, "OnCurrentStateReadResponseSuccess Invalid CurrentState!");
        break;
    }

    if (context != nullptr)
    {
        ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess context value: %d", *(static_cast<int *>(context)));
    }
}

void OnCurrentStateReadResponseFailure(void * context, CHIP_ERROR err)
{
    ChipLogProgress(AppServer, "OnCurrentStateReadResponseFailure called with %" CHIP_ERROR_FORMAT, err.Format());
}

void OnCurrentStateSubscriptionEstablished(void * context, SubscriptionId aSubscriptionId)
{
    ChipLogProgress(AppServer, "OnCurrentStateSubscriptionEstablished called");
    if (context != nullptr)
    {
        ChipLogProgress(AppServer, "OnCurrentStateSubscriptionEstablished context value: %d", *(static_cast<int *>(context)));
    }
}

void doCastingDemoActions(TargetEndpointInfo * endpoint)
{
    if (endpoint != nullptr && endpoint->IsInitialized())
    {
        if (endpoint->HasCluster(chip::app::Clusters::MediaPlayback::Id))
        {
            // Subscribe to MediaPlayback::CurrentState
            ChipLogProgress(AppServer,
                            "doCastingDemoActions requesting subscription on MediaPlayback:CurrentState on endpoint ID: %d",
                            endpoint->GetEndpointId());
            CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToCurrentState(
                endpoint, static_cast<void *>(&gInitialContextVal), OnCurrentStateReadResponseSuccess,
                OnCurrentStateReadResponseFailure, 0, 4000, OnCurrentStateSubscriptionEstablished);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer, "MediaPlayback_SubscribeToCurrentState call failed!");
            }
        }
        else
        {
            ChipLogProgress(AppServer,
                            "doCastingDemoActions: Not subscribing to MediaPlayback:CurrentState on endpoint ID %d as it does not "
                            "support the MediaPlayback cluster",
                            endpoint->GetEndpointId());
        }

        if (endpoint->HasCluster(chip::app::Clusters::ContentLauncher::Id))
        {
            // Send a ContentLauncher::LaunchURL command
            ChipLogProgress(AppServer, "doCastingDemoActions sending ContentLauncher:LaunchURL on endpoint ID: %d",
                            endpoint->GetEndpointId());
            CHIP_ERROR err = CastingServer::GetInstance()->ContentLauncherLaunchURL(endpoint, kContentUrl, kContentDisplayStr,
                                                                                    LaunchURLResponseCallback);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(AppServer, "ContentLauncherLaunchURL call failed!");
            }
        }
        else
        {
            ChipLogProgress(AppServer,
                            "doCastingDemoActions: Not sending ContentLauncher:LaunchURL on endpoint ID %d as it does not support "
                            "the ContentLauncher cluster",
                            endpoint->GetEndpointId());
        }
    }
}

void OnConnectionSuccess(TargetVideoPlayerInfo * videoPlayer)
{
    ChipLogProgress(AppServer,
                    "OnConnectionSuccess with Video Player(nodeId: 0x" ChipLogFormatX64
                    ", fabricIndex: %d, deviceName: %s, vendorId: %d, productId: "
                    "%d, deviceType: %d)",
                    ChipLogValueX64(videoPlayer->GetNodeId()), videoPlayer->GetFabricIndex(), videoPlayer->GetDeviceName(),
                    videoPlayer->GetVendorId(), videoPlayer->GetProductId(), videoPlayer->GetDeviceType());

    TargetEndpointInfo * endpoints = videoPlayer->GetEndpoints();
    if (endpoints != nullptr)
    {
        for (size_t i = 0; i < kMaxNumberOfEndpoints && endpoints[i].IsInitialized(); i++)
        {
            doCastingDemoActions(&endpoints[i]); // LaunchURL and Subscribe to CurrentState
        }
    }
}

void OnConnectionFailure(CHIP_ERROR err)
{
    ChipLogError(AppServer, "OnConnectionFailure error: %" CHIP_ERROR_FORMAT, err.AsString());
}

void OnNewOrUpdatedEndpoint(TargetEndpointInfo * endpoint)
{
    ChipLogProgress(AppServer, "OnNewOrUpdatedEndpoint called");
    doCastingDemoActions(endpoint); // LaunchURL and Subscribe to CurrentState
}

CHIP_ERROR ConnectToCachedVideoPlayer()
{
    TargetVideoPlayerInfo * cachedVideoPlayers = CastingServer::GetInstance()->ReadCachedTargetVideoPlayerInfos();
    if (cachedVideoPlayers != nullptr)
    {
        for (size_t i = 0; i < kMaxCachedVideoPlayers; i++)
        {
            if (cachedVideoPlayers[i].IsInitialized())
            {
                ChipLogProgress(AppServer, "Found a Cached video player with nodeId: 0x" ChipLogFormatX64 ", fabricIndex: %d",
                                ChipLogValueX64(cachedVideoPlayers[i].GetNodeId()), cachedVideoPlayers[i].GetFabricIndex());
                if (CastingServer::GetInstance()->VerifyOrEstablishConnection(
                        cachedVideoPlayers[i], OnConnectionSuccess, OnConnectionFailure, OnNewOrUpdatedEndpoint) == CHIP_NO_ERROR)
                {
                    ChipLogProgress(AppServer,
                                    "FindOrEstablish CASESession attempted for cached video player with nodeId: 0x" ChipLogFormatX64
                                    ", fabricIndex: %d",
                                    ChipLogValueX64(cachedVideoPlayers[i].GetNodeId()), cachedVideoPlayers[i].GetFabricIndex());
                    return CHIP_NO_ERROR;
                }
            }
        }
    }
    return CHIP_ERROR_INVALID_CASE_PARAMETER;
}

void HandleCommissioningCompleteCallback(CHIP_ERROR err)
{
    ChipLogProgress(AppServer, "HandleCommissioningCompleteCallback called with %" CHIP_ERROR_FORMAT, err.Format());
}

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
void HandleUDCSendExpiration(System::Layer * aSystemLayer, void * context)
{
    Dnssd::DiscoveredNodeData * selectedCommissioner = (Dnssd::DiscoveredNodeData *) context;

    // Send User Directed commissioning request
    ReturnOnFailure(CastingServer::GetInstance()->SendUserDirectedCommissioningRequest(selectedCommissioner));
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT

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