/*
 *
 *    Copyright (c) 2023 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 "EndpointListLoader.h"

#include "clusters/Clusters.h"
#include "core/BaseCluster.h"
#include "core/CastingPlayer.h"
#include "core/Types.h"
#include "support/CastingStore.h"

#include "app/clusters/bindings/BindingManager.h"
#include <app-common/zap-generated/cluster-objects.h>

namespace matter {
namespace casting {
namespace support {

using namespace matter::casting::core;

EndpointListLoader * EndpointListLoader::_endpointListLoader = nullptr;

EndpointListLoader::EndpointListLoader() {}

EndpointListLoader * EndpointListLoader::GetInstance()
{
    if (_endpointListLoader == nullptr)
    {
        _endpointListLoader = new EndpointListLoader();
    }
    return _endpointListLoader;
}

void EndpointListLoader::Initialize(chip::Messaging::ExchangeManager * exchangeMgr, const chip::SessionHandle * sessionHandle)
{
    mExchangeMgr   = exchangeMgr;
    mSessionHandle = sessionHandle;

    for (const auto & binding : chip::BindingTable::GetInstance())
    {
        if (binding.type == MATTER_UNICAST_BINDING && CastingPlayer::GetTargetCastingPlayer()->GetNodeId() == binding.nodeId)
        {
            // check to see if we discovered a new endpoint in the bindings
            chip::EndpointId endpointId                     = binding.remote;
            std::vector<memory::Strong<Endpoint>> endpoints = CastingPlayer::GetTargetCastingPlayer()->GetEndpoints();
            if (std::find_if(endpoints.begin(), endpoints.end(), [&endpointId](const memory::Strong<Endpoint> & endpoint) {
                    return endpoint->GetId() == endpointId;
                }) == endpoints.end())
            {
                mNewEndpointsToLoad++;
            }
        }
    }

    mPendingAttributeReads  = mNewEndpointsToLoad * kTotalDesiredAttributes;
    mEndpointAttributesList = new EndpointAttributes[mNewEndpointsToLoad];
    mEndpointServerLists    = new std::vector<chip::ClusterId>[mNewEndpointsToLoad];
}

CHIP_ERROR EndpointListLoader::Load()
{
    ChipLogProgress(AppServer, "EndpointListLoader::Load() called");

    VerifyOrReturnError(CastingPlayer::GetTargetCastingPlayer() != nullptr, CHIP_ERROR_INCORRECT_STATE);

    int endpointIndex      = -1;
    bool isLoadingRequired = false;
    for (const auto & binding : chip::BindingTable::GetInstance())
    {
        ChipLogProgress(AppServer,
                        "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)));
        if (binding.type == MATTER_UNICAST_BINDING && CastingPlayer::GetTargetCastingPlayer()->GetNodeId() == binding.nodeId)
        {
            // if we discovered a new Endpoint from the bindings, read its EndpointAttributes
            chip::EndpointId endpointId                     = binding.remote;
            std::vector<memory::Strong<Endpoint>> endpoints = CastingPlayer::GetTargetCastingPlayer()->GetEndpoints();
            if (std::find_if(endpoints.begin(), endpoints.end(), [&endpointId](const memory::Strong<Endpoint> & endpoint) {
                    return endpoint->GetId() == endpointId;
                }) == endpoints.end())
            {
                // Read attributes and mEndpointAttributesList for (endpointIndex + 1)
                ChipLogProgress(AppServer, "EndpointListLoader::Load Reading attributes for endpointId %d", endpointId);
                isLoadingRequired                            = true;
                mEndpointAttributesList[++endpointIndex].mId = endpointId;
                ReadVendorId(&mEndpointAttributesList[endpointIndex]);
                ReadProductId(&mEndpointAttributesList[endpointIndex]);
                ReadDeviceTypeList(&mEndpointAttributesList[endpointIndex]);
                ReadServerList(&mEndpointServerLists[endpointIndex], endpointId);
            }
        }
    }

    if (!isLoadingRequired)
    {
        ChipLogProgress(AppServer, "EndpointListLoader::Load found no new endpoints to load");
        mPendingAttributeReads = 0;
        Complete();
    }

    return CHIP_NO_ERROR;
}

void EndpointListLoader::Complete()
{
    ChipLogProgress(AppServer, "EndpointListLoader::Complete called with mPendingAttributeReads %lu", mPendingAttributeReads);
    if (mPendingAttributeReads > 0)
    {
        mPendingAttributeReads--;
    }

    if (mPendingAttributeReads == 0)
    {
        ChipLogProgress(AppServer, "EndpointListLoader::Complete Loading %lu endpoint(s)", mNewEndpointsToLoad);
        for (unsigned long i = 0; i < mNewEndpointsToLoad; i++)
        {
            EndpointAttributes endpointAttributes = mEndpointAttributesList[i];
            std::shared_ptr<Endpoint> endpoint =
                std::make_shared<Endpoint>(CastingPlayer::GetTargetCastingPlayer(), endpointAttributes);
            endpoint->RegisterClusters(mEndpointServerLists[i]);
            CastingPlayer::GetTargetCastingPlayer()->RegisterEndpoint(endpoint);
        }

        ChipLogProgress(AppServer, "EndpointListLoader::Complete finished Loading %lu endpoints", mNewEndpointsToLoad);

        // TODO cleanup
        // delete mEndpointAttributesList;
        mEndpointAttributesList = nullptr;
        // delete mEndpointServerLists;
        mEndpointServerLists = nullptr;
        mExchangeMgr         = nullptr;
        mSessionHandle       = nullptr;
        mNewEndpointsToLoad  = 0;

        // done loading endpoints, store TargetCastingPlayer
        CHIP_ERROR err = support::CastingStore::GetInstance()->AddOrUpdate(*CastingPlayer::GetTargetCastingPlayer());
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "CastingStore::AddOrUpdate() failed. Err: %" CHIP_ERROR_FORMAT, err.Format());
        }

        // callback client OnCompleted
        VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted,
                       ChipLogError(AppServer, "EndpointListLoader::Complete mOnCompleted() not found"));
        CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(CHIP_NO_ERROR, CastingPlayer::GetTargetCastingPlayer());
    }
}

CHIP_ERROR EndpointListLoader::ReadVendorId(EndpointAttributes * endpointAttributes)
{
    core::MediaClusterBase cluster(*mExchangeMgr, *mSessionHandle, endpointAttributes->mId);

    return cluster.template ReadAttribute<chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo>(
        endpointAttributes,
        [](void * context,
           chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo::DecodableArgType decodableVendorId) {
            EndpointAttributes * _endpointAttributes = static_cast<EndpointAttributes *>(context);
            _endpointAttributes->mVendorId           = decodableVendorId;
            EndpointListLoader::GetInstance()->Complete();
        },
        [](void * context, CHIP_ERROR err) {
            EndpointAttributes * _endpointAttributes = static_cast<EndpointAttributes *>(context);
            ChipLogError(AppServer, "EndpointListLoader ReadAttribute(VendorID) failed for endpointID %d. Err: %" CHIP_ERROR_FORMAT,
                         _endpointAttributes->mId, err.Format());
            EndpointListLoader::GetInstance()->Complete();
        });
}

CHIP_ERROR EndpointListLoader::ReadProductId(EndpointAttributes * endpointAttributes)
{
    core::MediaClusterBase cluster(*mExchangeMgr, *mSessionHandle, endpointAttributes->mId);

    return cluster.template ReadAttribute<chip::app::Clusters::ApplicationBasic::Attributes::ProductID::TypeInfo>(
        endpointAttributes,
        [](void * context,
           chip::app::Clusters::ApplicationBasic::Attributes::ProductID::TypeInfo::DecodableArgType decodableProductId) {
            EndpointAttributes * _endpointAttributes = static_cast<EndpointAttributes *>(context);
            _endpointAttributes->mProductId          = decodableProductId;
            EndpointListLoader::GetInstance()->Complete();
        },
        [](void * context, CHIP_ERROR err) {
            EndpointAttributes * _endpointAttributes = static_cast<EndpointAttributes *>(context);
            ChipLogError(AppServer,
                         "EndpointListLoader ReadAttribute(ProductID) failed for endpointID %d. Err: %" CHIP_ERROR_FORMAT,
                         _endpointAttributes->mId, err.Format());
            EndpointListLoader::GetInstance()->Complete();
        });
}

CHIP_ERROR EndpointListLoader::ReadDeviceTypeList(EndpointAttributes * endpointAttributes)
{
    core::MediaClusterBase cluster(*mExchangeMgr, *mSessionHandle, endpointAttributes->mId);

    return cluster.template ReadAttribute<chip::app::Clusters::Descriptor::Attributes::DeviceTypeList::TypeInfo>(
        endpointAttributes,
        [](void * context,
           chip::app::Clusters::Descriptor::Attributes::DeviceTypeList::TypeInfo::DecodableArgType decodableDeviceTypeList) {
            EndpointAttributes * _endpointAttributes = static_cast<EndpointAttributes *>(context);
            auto iter                                = decodableDeviceTypeList.begin();
            while (iter.Next())
            {
                auto & deviceType = iter.GetValue();
                _endpointAttributes->mDeviceTypeList.push_back(deviceType);
            }
            EndpointListLoader::GetInstance()->Complete();
        },
        [](void * context, CHIP_ERROR err) {
            EndpointAttributes * _endpointAttributes = static_cast<EndpointAttributes *>(context);
            ChipLogError(AppServer,
                         "EndpointListLoader ReadAttribute(DeviceTypeList) failed for endpointID %d. Err: %" CHIP_ERROR_FORMAT,
                         _endpointAttributes->mId, err.Format());
            EndpointListLoader::GetInstance()->Complete();
        });
}

CHIP_ERROR EndpointListLoader::ReadServerList(std::vector<chip::ClusterId> * endpointServerList, chip::EndpointId endpointId)
{
    core::MediaClusterBase cluster(*mExchangeMgr, *mSessionHandle, endpointId);

    return cluster.template ReadAttribute<chip::app::Clusters::Descriptor::Attributes::ServerList::TypeInfo>(
        endpointServerList,
        [](void * context,
           chip::app::Clusters::Descriptor::Attributes::ServerList::TypeInfo::DecodableArgType decodableServerList) {
            std::vector<chip::ClusterId> * _endpointServerList = static_cast<std::vector<chip::ClusterId> *>(context);
            auto iter                                          = decodableServerList.begin();
            while (iter.Next())
            {
                auto & clusterId = iter.GetValue();
                _endpointServerList->push_back(clusterId);
            }
            EndpointListLoader::GetInstance()->Complete();
        },
        [](void * context, CHIP_ERROR err) {
            ChipLogError(AppServer, "EndpointListLoader ReadAttribute(ServerList) failed. Err: %" CHIP_ERROR_FORMAT, err.Format());
            EndpointListLoader::GetInstance()->Complete();
        });
}

}; // namespace support
}; // namespace casting
}; // namespace matter
