/**
 *
 *    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.
 */

#include "TargetNavigatorManager.h"
#include <json/json.h>

using namespace std;
using namespace chip::app;
using namespace chip::app::Clusters::TargetNavigator;
using ContentAppAttributeDelegate = chip::AppPlatform::ContentAppAttributeDelegate;

TargetNavigatorManager::TargetNavigatorManager(ContentAppAttributeDelegate * attributeDelegate, std::list<std::string> targets,
                                               uint8_t currentTarget) :
    mAttributeDelegate(attributeDelegate)
{
    mTargets       = targets;
    mCurrentTarget = currentTarget;
}

CHIP_ERROR TargetNavigatorManager::HandleGetTargetList(AttributeValueEncoder & aEncoder)
{
    ChipLogProgress(Zcl, "TargetNavigatorManager::HandleNavigateTarget");

    if (mAttributeDelegate != nullptr)
    {
        chip::app::ConcreteReadAttributePath aPath(mEndpointId, chip::app::Clusters::TargetNavigator::Id,
                                                   chip::app::Clusters::TargetNavigator::Attributes::TargetList::Id);
        const char * resStr = mAttributeDelegate->Read(aPath);
        ChipLogProgress(Zcl, "TargetNavigatorManager::HandleNavigateTarget 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::TargetNavigator::Attributes::TargetList::Id);
                ChipLogProgress(Zcl, "TargetNavigatorManager::HandleNavigateTarget response parsing done. reading attr %s",
                                attrId.c_str());
                if (value[attrId].isArray())
                {
                    return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
                        int i                = 0;
                        std::string targetId = to_string(
                            static_cast<uint32_t>(chip::app::Clusters::TargetNavigator::Structs::TargetInfo::Fields::kIdentifier));
                        std::string targetName = to_string(
                            static_cast<uint32_t>(chip::app::Clusters::TargetNavigator::Structs::TargetInfo::Fields::kName));
                        for (Json::Value & entry : value[attrId])
                        {
                            if (!entry[targetId].isUInt() || !entry[targetName].isString() || entry[targetId].asUInt() > 255)
                            {
                                // invalid target ID. Ignore.
                                ChipLogError(Zcl, "TargetNavigatorManager::HandleNavigateTarget invalid target ignored");
                                i++;
                                continue;
                            }
                            Structs::TargetInfo::Type outputInfo;
                            outputInfo.identifier = static_cast<uint8_t>(entry[targetId].asUInt());
                            outputInfo.name       = CharSpan::fromCharString(entry[targetName].asCString());
                            ReturnErrorOnFailure(encoder.Encode(outputInfo));
                            i++;
                        }
                        return CHIP_NO_ERROR;
                    });
                }
            }
        }
    }

    // NOTE: the ids for each target start at 1 so that we can reserve 0 as "no current target"
    return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
        int i = 0;
        for (std::string & entry : mTargets)
        {
            Structs::TargetInfo::Type outputInfo;
            outputInfo.identifier = static_cast<uint8_t>(i + 1);
            outputInfo.name       = CharSpan::fromCharString(entry.c_str());
            ReturnErrorOnFailure(encoder.Encode(outputInfo));
            i++;
        }
        return CHIP_NO_ERROR;
    });
}

uint8_t TargetNavigatorManager::HandleGetCurrentTarget()
{
    ChipLogProgress(Zcl, "TargetNavigatorManager::HandleGetCurrentTarget");

    if (mAttributeDelegate != nullptr)
    {
        chip::app::ConcreteReadAttributePath aPath(mEndpointId, chip::app::Clusters::TargetNavigator::Id,
                                                   chip::app::Clusters::TargetNavigator::Attributes::TargetList::Id);
        const char * resStr = mAttributeDelegate->Read(aPath);
        ChipLogProgress(Zcl, "TargetNavigatorManager::HandleGetCurrentTarget 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::TargetNavigator::Attributes::CurrentTarget::Id);
                ChipLogProgress(Zcl, "TargetNavigatorManager::HandleGetCurrentTarget response parsing done. reading attr %s",
                                attrId.c_str());
                if (value[attrId].isUInt() && value[attrId].asUInt() < 256)
                {
                    return static_cast<uint8_t>(value[attrId].asUInt());
                }
            }
        }
    }

    return mCurrentTarget;
}

void TargetNavigatorManager::HandleNavigateTarget(CommandResponseHelper<NavigateTargetResponseType> & helper,
                                                  const uint64_t & target, const CharSpan & data)
{
    NavigateTargetResponseType response;
    if (target == kNoCurrentTarget || target > mTargets.size())
    {
        response.data   = chip::MakeOptional(CharSpan::fromCharString("error"));
        response.status = TargetNavigatorStatusEnum::kTargetNotFound;
        helper.Success(response);
        return;
    }
    mCurrentTarget = static_cast<uint8_t>(target);

    response.data   = chip::MakeOptional(CharSpan::fromCharString("data response"));
    response.status = TargetNavigatorStatusEnum::kSuccess;
    helper.Success(response);
}
