/*
 *
 *    Copyright (c) 2021 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 "AppContentLauncherManager.h"
#include "../../java/ContentAppAttributeDelegate.h"
#include <json/json.h>

using namespace std;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::DataModel;
using namespace chip::app::Clusters::ContentLauncher;
using ContentAppAttributeDelegate = chip::AppPlatform::ContentAppAttributeDelegate;

AppContentLauncherManager::AppContentLauncherManager(ContentAppAttributeDelegate * attributeDelegate,
                                                     list<std::string> acceptHeaderList, uint32_t supportedStreamingProtocols) :
    mAttributeDelegate(attributeDelegate)
{
    mAcceptHeaderList            = acceptHeaderList;
    mSupportedStreamingProtocols = supportedStreamingProtocols;
}

void AppContentLauncherManager::HandleLaunchContent(CommandResponseHelper<LaunchResponseType> & helper,
                                                    const DecodableList<ParameterType> & parameterList, bool autoplay,
                                                    const CharSpan & data)
{
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleLaunchContent for endpoint %d", mEndpointId);
    string dataString(data.data(), data.size());

    ChipLogProgress(Zcl, " AutoPlay=%s", (autoplay ? "true" : "false"));

    bool foundMatch = false;
    auto iter       = parameterList.begin();
    while (iter.Next())
    {
        auto & parameterType = iter.GetValue();
        ChipLogProgress(Zcl, " TEST CASE found match=Example TV Show type=%d", static_cast<uint16_t>(parameterType.type));
        foundMatch = true;
    }

    if (!foundMatch)
    {
        ChipLogProgress(Zcl, " TEST CASE did not find a match");
    }

    LaunchResponseType response;
    // TODO: Insert code here
    response.data   = chip::MakeOptional(CharSpan::fromCharString("exampleData"));
    response.status = ContentLauncher::ContentLaunchStatusEnum::kSuccess;
    helper.Success(response);
}

void AppContentLauncherManager::HandleLaunchUrl(CommandResponseHelper<LaunchResponseType> & helper, const CharSpan & contentUrl,
                                                const CharSpan & displayString, const BrandingInformationType & brandingInformation)
{
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleLaunchUrl");

    string contentUrlString(contentUrl.data(), contentUrl.size());
    string displayStringString(displayString.data(), displayString.size());

    // TODO: Insert code here
    LaunchResponseType response;
    response.data   = chip::MakeOptional(CharSpan::fromCharString("Success"));
    response.status = ContentLauncher::ContentLaunchStatusEnum::kSuccess;
    helper.Success(response);
}

CHIP_ERROR AppContentLauncherManager::HandleGetAcceptHeaderList(AttributeValueEncoder & aEncoder)
{
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetAcceptHeaderList");
    chip::app::ConcreteReadAttributePath aPath(mEndpointId, chip::app::Clusters::ContentLauncher::Id,
                                               chip::app::Clusters::ContentLauncher::Attributes::AcceptHeader::Id);
    const char * resStr = mAttributeDelegate->Read(aPath);
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols response %s", resStr);

    if (resStr != nullptr && *resStr != 0)
    {
        Json::Reader reader;
        Json::Value value;
        if (reader.parse(resStr, value))
        {
            std::string attrId = to_string(chip::app::Clusters::ContentLauncher::Attributes::AcceptHeader::Id);
            ChipLogProgress(
                Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols response parsing done. reading attr %s",
                attrId.c_str());
            if (value[attrId].isArray())
            {
                mAcceptHeaderList.clear();
                for (Json::Value & entry : value[attrId])
                {
                    mAcceptHeaderList.push_back(entry.asString());
                }
            }
        }
    }

    return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
        for (std::string & entry : mAcceptHeaderList)
        {
            CharSpan data = CharSpan::fromCharString(entry.c_str());
            ReturnErrorOnFailure(encoder.Encode(data));
        }
        return CHIP_NO_ERROR;
    });
}

uint32_t AppContentLauncherManager::HandleGetSupportedStreamingProtocols()
{
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols");
    chip::app::ConcreteReadAttributePath aPath(mEndpointId, chip::app::Clusters::ContentLauncher::Id,
                                               chip::app::Clusters::ContentLauncher::Attributes::SupportedStreamingProtocols::Id);
    const char * resStr = mAttributeDelegate->Read(aPath);
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols response %s", resStr);

    if (resStr == nullptr || *resStr == 0)
    {
        return mSupportedStreamingProtocols;
    }

    Json::Reader reader;
    Json::Value value;
    if (!reader.parse(resStr, value))
    {
        return mSupportedStreamingProtocols;
    }
    std::string attrId = to_string(chip::app::Clusters::ContentLauncher::Attributes::SupportedStreamingProtocols::Id);
    ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols response parsing done. reading attr %s",
                    attrId.c_str());
    if (!value[attrId].empty())
    {
        uint32_t supportedStreamingProtocols = static_cast<uint32_t>(value[attrId].asInt());
        mSupportedStreamingProtocols         = supportedStreamingProtocols;
    }
    return mSupportedStreamingProtocols;
}

uint32_t AppContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint)
{
    if (endpoint >= EMBER_AF_CONTENT_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT)
    {
        return mDynamicEndpointFeatureMap;
    }

    uint32_t featureMap = 0;
    Attributes::FeatureMap::Get(endpoint, &featureMap);
    return featureMap;
}
