/*
 *
 *    Copyright (c) 2020 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
 * @brief Implementation for the Binding Server Cluster
 ***************************************************************************/

#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteAttributePath.h>
#include <app/clusters/bindings/bindings.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <app/util/config.h>
#include <lib/support/logging/CHIPLogging.h>
#include <protocols/interaction_model/StatusCode.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using TargetStructType         = Binding::Structs::TargetStruct::Type;
using DecodableBindingListType = Binding::Attributes::Binding::TypeInfo::DecodableType;

// TODO: add binding table to the persistent storage
namespace {

class BindingTableAccess : public AttributeAccessInterface
{
public:
    // Register for the Binding cluster on all endpoints.
    BindingTableAccess() : AttributeAccessInterface(NullOptional, Binding::Id) {}

    CHIP_ERROR Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder) override;
    CHIP_ERROR Write(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder) override;
    void OnListWriteEnd(const app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override;

private:
    CHIP_ERROR ReadBindingTable(EndpointId endpoint, AttributeValueEncoder & encoder);
    CHIP_ERROR WriteBindingTable(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder);

    CHIP_ERROR NotifyBindingsChanged();

    FabricIndex mAccessingFabricIndex;
};

BindingTableAccess gAttrAccess;

bool IsValidBinding(const EndpointId localEndpoint, const TargetStructType & entry)
{
    bool isValid = false;

    // Entry has endpoint, node id and no group id
    if (!entry.group.HasValue() && entry.endpoint.HasValue() && entry.node.HasValue())
    {
        if (entry.cluster.HasValue())
        {
            if (emberAfContainsClient(localEndpoint, entry.cluster.Value()))
            {
                // Valid node/endpoint/cluster binding
                isValid = true;
            }
        }
        else
        {
            // Valid node/endpoint (no cluster id) binding
            isValid = true;
        }
    }
    // Entry has group id and no endpoint and node id
    else if (!entry.endpoint.HasValue() && !entry.node.HasValue() && entry.group.HasValue())
    {
        // Valid group binding
        isValid = true;
    }

    return isValid;
}

CHIP_ERROR CheckValidBindingList(const EndpointId localEndpoint, const DecodableBindingListType & bindingList,
                                 FabricIndex accessingFabricIndex)
{
    size_t listSize = 0;
    auto iter       = bindingList.begin();
    while (iter.Next())
    {
        VerifyOrReturnError(IsValidBinding(localEndpoint, iter.GetValue()), CHIP_IM_GLOBAL_STATUS(ConstraintError));
        listSize++;
    }
    ReturnErrorOnFailure(iter.GetStatus());

    // Check binding table size
    uint8_t oldListSize = 0;
    for (const auto & entry : BindingTable::GetInstance())
    {
        if (entry.fabricIndex == accessingFabricIndex)
        {
            oldListSize++;
        }
    }
    ReturnErrorCodeIf(BindingTable::GetInstance().Size() - oldListSize + listSize > EMBER_BINDING_TABLE_SIZE,
                      CHIP_IM_GLOBAL_STATUS(ResourceExhausted));
    return CHIP_NO_ERROR;
}

CHIP_ERROR CreateBindingEntry(const TargetStructType & entry, EndpointId localEndpoint)
{
    EmberBindingTableEntry bindingEntry;

    if (entry.group.HasValue())
    {
        bindingEntry = EmberBindingTableEntry::ForGroup(entry.fabricIndex, entry.group.Value(), localEndpoint, entry.cluster);
    }
    else
    {
        bindingEntry = EmberBindingTableEntry::ForNode(entry.fabricIndex, entry.node.Value(), localEndpoint, entry.endpoint.Value(),
                                                       entry.cluster);
    }

    return AddBindingEntry(bindingEntry);
}

CHIP_ERROR BindingTableAccess::Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder)
{
    switch (path.mAttributeId)
    {
    case Binding::Attributes::Binding::Id:
        return ReadBindingTable(path.mEndpointId, encoder);
    default:
        break;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR BindingTableAccess::ReadBindingTable(EndpointId endpoint, AttributeValueEncoder & encoder)
{
    return encoder.EncodeList([&](const auto & subEncoder) {
        for (const EmberBindingTableEntry & entry : BindingTable::GetInstance())
        {
            if (entry.local == endpoint && entry.type == EMBER_UNICAST_BINDING)
            {
                Binding::Structs::TargetStruct::Type value = {
                    .node        = MakeOptional(entry.nodeId),
                    .group       = NullOptional,
                    .endpoint    = MakeOptional(entry.remote),
                    .cluster     = entry.clusterId,
                    .fabricIndex = entry.fabricIndex,
                };
                ReturnErrorOnFailure(subEncoder.Encode(value));
            }
            else if (entry.local == endpoint && entry.type == EMBER_MULTICAST_BINDING)
            {
                Binding::Structs::TargetStruct::Type value = {
                    .node        = NullOptional,
                    .group       = MakeOptional(entry.groupId),
                    .endpoint    = NullOptional,
                    .cluster     = entry.clusterId,
                    .fabricIndex = entry.fabricIndex,
                };
                ReturnErrorOnFailure(subEncoder.Encode(value));
            }
        }
        return CHIP_NO_ERROR;
    });
}

CHIP_ERROR BindingTableAccess::Write(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder)
{
    switch (path.mAttributeId)
    {
    case Binding::Attributes::Binding::Id:
        return WriteBindingTable(path, decoder);
    default:
        break;
    }
    return CHIP_NO_ERROR;
}

void BindingTableAccess::OnListWriteEnd(const app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful)
{
    // Notify binding table has changed
    LogErrorOnFailure(NotifyBindingsChanged());
}

CHIP_ERROR BindingTableAccess::WriteBindingTable(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder)
{
    mAccessingFabricIndex = decoder.AccessingFabricIndex();
    if (!path.IsListOperation() || path.mListOp == ConcreteDataAttributePath::ListOperation::ReplaceAll)
    {
        DecodableBindingListType newBindingList;

        ReturnErrorOnFailure(decoder.Decode(newBindingList));
        ReturnErrorOnFailure(CheckValidBindingList(path.mEndpointId, newBindingList, mAccessingFabricIndex));

        // Clear all entries for the current accessing fabric and endpoint
        auto bindingTableIter = BindingTable::GetInstance().begin();
        while (bindingTableIter != BindingTable::GetInstance().end())
        {
            if (bindingTableIter->local == path.mEndpointId && bindingTableIter->fabricIndex == mAccessingFabricIndex)
            {
                if (bindingTableIter->type == EMBER_UNICAST_BINDING)
                {
                    BindingManager::GetInstance().UnicastBindingRemoved(bindingTableIter.GetIndex());
                }
                ReturnErrorOnFailure(BindingTable::GetInstance().RemoveAt(bindingTableIter));
            }
            else
            {
                ++bindingTableIter;
            }
        }

        // Add new entries
        auto iter      = newBindingList.begin();
        CHIP_ERROR err = CHIP_NO_ERROR;
        while (iter.Next() && err == CHIP_NO_ERROR)
        {
            err = CreateBindingEntry(iter.GetValue(), path.mEndpointId);
        }

        // If this was not caused by a list operation, OnListWriteEnd is not going to be triggered
        // so a notification is sent here.
        if (!path.IsListOperation())
        {
            // Notify binding table has changed
            LogErrorOnFailure(NotifyBindingsChanged());
        }
        return err;
    }
    if (path.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem)
    {
        TargetStructType target;
        ReturnErrorOnFailure(decoder.Decode(target));
        if (!IsValidBinding(path.mEndpointId, target))
        {
            return CHIP_IM_GLOBAL_STATUS(ConstraintError);
        }
        return CreateBindingEntry(target, path.mEndpointId);
    }
    return CHIP_IM_GLOBAL_STATUS(UnsupportedWrite);
}

CHIP_ERROR BindingTableAccess::NotifyBindingsChanged()
{
    DeviceLayer::ChipDeviceEvent event;
    event.Type                        = DeviceLayer::DeviceEventType::kBindingsChangedViaCluster;
    event.BindingsChanged.fabricIndex = mAccessingFabricIndex;
    return chip::DeviceLayer::PlatformMgr().PostEvent(&event);
}

} // namespace

void MatterBindingPluginServerInitCallback()
{
    registerAttributeAccessOverride(&gAttrAccess);
}

CHIP_ERROR AddBindingEntry(const EmberBindingTableEntry & entry)
{
    CHIP_ERROR err = BindingTable::GetInstance().Add(entry);
    if (err == CHIP_ERROR_NO_MEMORY)
    {
        return CHIP_IM_GLOBAL_STATUS(ResourceExhausted);
    }

    if (err != CHIP_NO_ERROR)
    {
        return err;
    }

    if (entry.type == EMBER_UNICAST_BINDING)
    {
        err = BindingManager::GetInstance().UnicastBindingCreated(entry.fabricIndex, entry.nodeId);
        if (err != CHIP_NO_ERROR)
        {
            // Unicast connection failure can happen if peer is offline. We'll retry connection on-demand.
            ChipLogError(
                Zcl, "Binding: Failed to create session for unicast binding to device " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
                ChipLogValueX64(entry.nodeId), err.Format());
        }
    }

    return CHIP_NO_ERROR;
}
