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

/**
 *    @file
 *      This file defines a basic implementation of SubscriptionResumptionStorage that
 *      persists subscriptions in a flat list in TLV.
 */

#include <app/SimpleSubscriptionResumptionStorage.h>

#include <lib/support/Base64.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace app {

constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kPeerNodeIdTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kFabricIndexTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kSubscriptionIdTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kMinIntervalTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kMaxIntervalTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kFabricFilteredTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kAttributePathsListTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kEventPathsListTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kAttributePathTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kEventPathTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kEndpointIdTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kClusterIdTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kAttributeIdTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kEventIdTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kEventPathTypeTag;
constexpr TLV::Tag SimpleSubscriptionResumptionStorage::kResumptionRetriesTag;

SimpleSubscriptionResumptionStorage::SimpleSubscriptionInfoIterator::SimpleSubscriptionInfoIterator(
    SimpleSubscriptionResumptionStorage & storage) :
    mStorage(storage)
{
    mNextIndex = 0;
}

size_t SimpleSubscriptionResumptionStorage::SimpleSubscriptionInfoIterator::Count()
{
    return static_cast<size_t>(mStorage.Count());
}

bool SimpleSubscriptionResumptionStorage::SimpleSubscriptionInfoIterator::Next(SubscriptionInfo & output)
{
    for (; mNextIndex < CHIP_IM_MAX_NUM_SUBSCRIPTIONS; mNextIndex++)
    {
        CHIP_ERROR err = mStorage.Load(mNextIndex, output);
        if (err == CHIP_NO_ERROR)
        {
            // increment index for the next call
            mNextIndex++;
            return true;
        }

        if (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
        {
            ChipLogError(DataManagement, "Failed to load subscription at index %u error %" CHIP_ERROR_FORMAT,
                         static_cast<unsigned>(mNextIndex), err.Format());
            mStorage.Delete(mNextIndex);
        }
    }

    return false;
}

void SimpleSubscriptionResumptionStorage::SimpleSubscriptionInfoIterator::Release()
{
    mStorage.mSubscriptionInfoIterators.ReleaseObject(this);
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::Init(PersistentStorageDelegate * storage)
{
    VerifyOrReturnError(storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    mStorage = storage;

    uint16_t countMax;
    uint16_t len = sizeof(countMax);
    CHIP_ERROR err =
        mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::SubscriptionResumptionMaxCount().KeyName(), &countMax, len);
    // If there's a previous countMax and it's larger than CHIP_IM_MAX_NUM_SUBSCRIPTIONS,
    // clean up subscriptions beyond the limit
    if ((err == CHIP_NO_ERROR) && (countMax != CHIP_IM_MAX_NUM_SUBSCRIPTIONS))
    {
        for (uint16_t subscriptionIndex = CHIP_IM_MAX_NUM_SUBSCRIPTIONS; subscriptionIndex < countMax; subscriptionIndex++)
        {
            Delete(subscriptionIndex);
        }
    }

    // Always save the current CHIP_IM_MAX_NUM_SUBSCRIPTIONS
    uint16_t countMaxToSave = CHIP_IM_MAX_NUM_SUBSCRIPTIONS;
    ReturnErrorOnFailure(mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::SubscriptionResumptionMaxCount().KeyName(),
                                                   &countMaxToSave, sizeof(uint16_t)));

    return CHIP_NO_ERROR;
}

SubscriptionResumptionStorage::SubscriptionInfoIterator * SimpleSubscriptionResumptionStorage::IterateSubscriptions()
{
    return mSubscriptionInfoIterators.CreateObject(*this);
}

uint16_t SimpleSubscriptionResumptionStorage::Count()
{
    uint16_t subscriptionCount = 0;
    for (uint16_t subscriptionIndex = 0; subscriptionIndex < CHIP_IM_MAX_NUM_SUBSCRIPTIONS; subscriptionIndex++)
    {
        if (mStorage->SyncDoesKeyExist(DefaultStorageKeyAllocator::SubscriptionResumption(subscriptionIndex).KeyName()))
        {
            subscriptionCount++;
        }
    }

    return subscriptionCount;
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::Delete(uint16_t subscriptionIndex)
{
    return mStorage->SyncDeleteKeyValue(DefaultStorageKeyAllocator::SubscriptionResumption(subscriptionIndex).KeyName());
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::Load(uint16_t subscriptionIndex, SubscriptionInfo & subscriptionInfo)
{
    Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
    backingBuffer.Calloc(MaxSubscriptionSize());
    VerifyOrReturnError(backingBuffer.Get() != nullptr, CHIP_ERROR_NO_MEMORY);

    uint16_t len = static_cast<uint16_t>(MaxSubscriptionSize());
    ReturnErrorOnFailure(mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::SubscriptionResumption(subscriptionIndex).KeyName(),
                                                   backingBuffer.Get(), len));

    TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), len);

    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));

    TLV::TLVType subscriptionContainerType;
    ReturnErrorOnFailure(reader.EnterContainer(subscriptionContainerType));

    // Node ID
    ReturnErrorOnFailure(reader.Next(kPeerNodeIdTag));
    ReturnErrorOnFailure(reader.Get(subscriptionInfo.mNodeId));

    // Fabric index
    ReturnErrorOnFailure(reader.Next(kFabricIndexTag));
    ReturnErrorOnFailure(reader.Get(subscriptionInfo.mFabricIndex));

    // Subscription ID
    ReturnErrorOnFailure(reader.Next(kSubscriptionIdTag));
    ReturnErrorOnFailure(reader.Get(subscriptionInfo.mSubscriptionId));

    // Min interval
    ReturnErrorOnFailure(reader.Next(kMinIntervalTag));
    ReturnErrorOnFailure(reader.Get(subscriptionInfo.mMinInterval));

    // Max interval
    ReturnErrorOnFailure(reader.Next(kMaxIntervalTag));
    ReturnErrorOnFailure(reader.Get(subscriptionInfo.mMaxInterval));

    // Fabric filtered boolean
    ReturnErrorOnFailure(reader.Next(kFabricFilteredTag));
    ReturnErrorOnFailure(reader.Get(subscriptionInfo.mFabricFiltered));

    // Attribute Paths
    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_List, kAttributePathsListTag));
    TLV::TLVType attributesListType;
    ReturnErrorOnFailure(reader.EnterContainer(attributesListType));

    size_t pathCount = 0;
    ReturnErrorOnFailure(reader.CountRemainingInContainer(&pathCount));

    // If a stack struct is being reused to iterate, free the previous paths ScopedMemoryBuffer
    subscriptionInfo.mAttributePaths.Free();
    if (pathCount)
    {
        subscriptionInfo.mAttributePaths.Calloc(pathCount);
        VerifyOrReturnError(subscriptionInfo.mAttributePaths.Get() != nullptr, CHIP_ERROR_NO_MEMORY);
        for (size_t pathIndex = 0; pathIndex < pathCount; pathIndex++)
        {
            ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, kAttributePathTag));
            TLV::TLVType attributeContainerType;
            ReturnErrorOnFailure(reader.EnterContainer(attributeContainerType));

            ReturnErrorOnFailure(reader.Next(kEndpointIdTag));
            ReturnErrorOnFailure(reader.Get(subscriptionInfo.mAttributePaths[pathIndex].mEndpointId));

            ReturnErrorOnFailure(reader.Next(kClusterIdTag));
            ReturnErrorOnFailure(reader.Get(subscriptionInfo.mAttributePaths[pathIndex].mClusterId));

            ReturnErrorOnFailure(reader.Next(kAttributeIdTag));
            ReturnErrorOnFailure(reader.Get(subscriptionInfo.mAttributePaths[pathIndex].mAttributeId));

            ReturnErrorOnFailure(reader.ExitContainer(attributeContainerType));
        }
    }
    ReturnErrorOnFailure(reader.ExitContainer(attributesListType));

    // Event Paths
    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_List, kEventPathsListTag));
    TLV::TLVType eventsListType;
    ReturnErrorOnFailure(reader.EnterContainer(eventsListType));

    ReturnErrorOnFailure(reader.CountRemainingInContainer(&pathCount));

    // If a stack struct is being reused to iterate, free the previous paths ScopedMemoryBuffer
    subscriptionInfo.mEventPaths.Free();
    if (pathCount)
    {
        subscriptionInfo.mEventPaths.Calloc(pathCount);
        VerifyOrReturnError(subscriptionInfo.mEventPaths.Get() != nullptr, CHIP_ERROR_NO_MEMORY);
        for (size_t pathIndex = 0; pathIndex < pathCount; pathIndex++)
        {
            ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, kEventPathTag));
            TLV::TLVType eventContainerType;
            ReturnErrorOnFailure(reader.EnterContainer(eventContainerType));

            EventPathType eventPathType;
            ReturnErrorOnFailure(reader.Next(kEventPathTypeTag));
            ReturnErrorOnFailure(reader.Get(eventPathType));

            subscriptionInfo.mEventPaths[pathIndex].mIsUrgentEvent = (eventPathType == EventPathType::kUrgent);

            ReturnErrorOnFailure(reader.Next(kEndpointIdTag));
            ReturnErrorOnFailure(reader.Get(subscriptionInfo.mEventPaths[pathIndex].mEndpointId));

            ReturnErrorOnFailure(reader.Next(kClusterIdTag));
            ReturnErrorOnFailure(reader.Get(subscriptionInfo.mEventPaths[pathIndex].mClusterId));

            ReturnErrorOnFailure(reader.Next(kEventIdTag));
            ReturnErrorOnFailure(reader.Get(subscriptionInfo.mEventPaths[pathIndex].mEventId));

            ReturnErrorOnFailure(reader.ExitContainer(eventContainerType));
        }
    }
    ReturnErrorOnFailure(reader.ExitContainer(eventsListType));

#if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
    // If the reader cannot get resumption retries, set it to 0 for subscriptionInfo
    if (reader.Next(kResumptionRetriesTag) == CHIP_NO_ERROR)
    {
        ReturnErrorOnFailure(reader.Get(subscriptionInfo.mResumptionRetries));
    }
    else
    {
        subscriptionInfo.mResumptionRetries = 0;
    }
#endif // CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION

    ReturnErrorOnFailure(reader.ExitContainer(subscriptionContainerType));

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::Save(TLV::TLVWriter & writer, SubscriptionInfo & subscriptionInfo)
{
    TLV::TLVType subscriptionContainerType;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, subscriptionContainerType));
    ReturnErrorOnFailure(writer.Put(kPeerNodeIdTag, subscriptionInfo.mNodeId));
    ReturnErrorOnFailure(writer.Put(kFabricIndexTag, subscriptionInfo.mFabricIndex));
    ReturnErrorOnFailure(writer.Put(kSubscriptionIdTag, subscriptionInfo.mSubscriptionId));
    ReturnErrorOnFailure(writer.Put(kMinIntervalTag, subscriptionInfo.mMinInterval));
    ReturnErrorOnFailure(writer.Put(kMaxIntervalTag, subscriptionInfo.mMaxInterval));
    ReturnErrorOnFailure(writer.Put(kFabricFilteredTag, subscriptionInfo.mFabricFiltered));

    // Attribute paths
    TLV::TLVType attributesListType;
    ReturnErrorOnFailure(writer.StartContainer(kAttributePathsListTag, TLV::kTLVType_List, attributesListType));
    for (size_t pathIndex = 0; pathIndex < subscriptionInfo.mAttributePaths.AllocatedSize(); pathIndex++)
    {
        TLV::TLVType attributeContainerType = TLV::kTLVType_Structure;
        ReturnErrorOnFailure(writer.StartContainer(kAttributePathTag, TLV::kTLVType_Structure, attributeContainerType));

        ReturnErrorOnFailure(writer.Put(kEndpointIdTag, subscriptionInfo.mAttributePaths[pathIndex].mEndpointId));
        ReturnErrorOnFailure(writer.Put(kClusterIdTag, subscriptionInfo.mAttributePaths[pathIndex].mClusterId));
        ReturnErrorOnFailure(writer.Put(kAttributeIdTag, subscriptionInfo.mAttributePaths[pathIndex].mAttributeId));

        ReturnErrorOnFailure(writer.EndContainer(attributeContainerType));
    }
    ReturnErrorOnFailure(writer.EndContainer(attributesListType));

    // Event paths
    TLV::TLVType eventsListType;
    ReturnErrorOnFailure(writer.StartContainer(kEventPathsListTag, TLV::kTLVType_List, eventsListType));
    for (size_t pathIndex = 0; pathIndex < subscriptionInfo.mEventPaths.AllocatedSize(); pathIndex++)
    {
        TLV::TLVType eventContainerType = TLV::kTLVType_Structure;
        ReturnErrorOnFailure(writer.StartContainer(kEventPathTag, TLV::kTLVType_Structure, eventContainerType));

        if (subscriptionInfo.mEventPaths[pathIndex].mIsUrgentEvent)
        {
            ReturnErrorOnFailure(writer.Put(kEventPathTypeTag, EventPathType::kUrgent));
        }
        else
        {
            ReturnErrorOnFailure(writer.Put(kEventPathTypeTag, EventPathType::kNonUrgent));
        }
        ReturnErrorOnFailure(writer.Put(kEndpointIdTag, subscriptionInfo.mEventPaths[pathIndex].mEndpointId));
        ReturnErrorOnFailure(writer.Put(kClusterIdTag, subscriptionInfo.mEventPaths[pathIndex].mClusterId));
        ReturnErrorOnFailure(writer.Put(kEventIdTag, subscriptionInfo.mEventPaths[pathIndex].mEventId));

        ReturnErrorOnFailure(writer.EndContainer(eventContainerType));
    }
    ReturnErrorOnFailure(writer.EndContainer(eventsListType));
#if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
    ReturnErrorOnFailure(writer.Put(kResumptionRetriesTag, subscriptionInfo.mResumptionRetries));
#endif // CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION

    ReturnErrorOnFailure(writer.EndContainer(subscriptionContainerType));

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::Save(SubscriptionInfo & subscriptionInfo)
{
    // Find empty index or duplicate if exists
    uint16_t subscriptionIndex;
    uint16_t firstEmptySubscriptionIndex = CHIP_IM_MAX_NUM_SUBSCRIPTIONS; // initialize to out of bounds as "not set"
    for (subscriptionIndex = 0; subscriptionIndex < CHIP_IM_MAX_NUM_SUBSCRIPTIONS; subscriptionIndex++)
    {
        SubscriptionInfo currentSubscriptionInfo;
        CHIP_ERROR err = Load(subscriptionIndex, currentSubscriptionInfo);

        // if empty and firstEmptySubscriptionIndex isn't set yet, then mark empty spot
        if ((firstEmptySubscriptionIndex == CHIP_IM_MAX_NUM_SUBSCRIPTIONS) && (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
        {
            firstEmptySubscriptionIndex = subscriptionIndex;
        }

        // delete duplicate
        if (err == CHIP_NO_ERROR)
        {
            if ((subscriptionInfo.mNodeId == currentSubscriptionInfo.mNodeId) &&
                (subscriptionInfo.mFabricIndex == currentSubscriptionInfo.mFabricIndex) &&
                (subscriptionInfo.mSubscriptionId == currentSubscriptionInfo.mSubscriptionId))
            {
                Delete(subscriptionIndex);
                // if duplicate is the first empty spot, then also set it
                if (firstEmptySubscriptionIndex == CHIP_IM_MAX_NUM_SUBSCRIPTIONS)
                {
                    firstEmptySubscriptionIndex = subscriptionIndex;
                }
            }
        }
    }

    // Fail if no empty space
    if (firstEmptySubscriptionIndex == CHIP_IM_MAX_NUM_SUBSCRIPTIONS)
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    // Now construct subscription state and save
    Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
    backingBuffer.Calloc(MaxSubscriptionSize());
    VerifyOrReturnError(backingBuffer.Get() != nullptr, CHIP_ERROR_NO_MEMORY);

    TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), MaxSubscriptionSize());

    ReturnErrorOnFailure(Save(writer, subscriptionInfo));

    const auto len = writer.GetLengthWritten();
    VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);

    writer.Finalize(backingBuffer);

    ReturnErrorOnFailure(
        mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::SubscriptionResumption(firstEmptySubscriptionIndex).KeyName(),
                                  backingBuffer.Get(), static_cast<uint16_t>(len)));

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::Delete(NodeId nodeId, FabricIndex fabricIndex, SubscriptionId subscriptionId)
{
    bool subscriptionFound   = false;
    CHIP_ERROR lastDeleteErr = CHIP_NO_ERROR;

    uint16_t remainingSubscriptionsCount = 0;
    for (uint16_t subscriptionIndex = 0; subscriptionIndex < CHIP_IM_MAX_NUM_SUBSCRIPTIONS; subscriptionIndex++)
    {
        SubscriptionInfo subscriptionInfo;
        CHIP_ERROR err = Load(subscriptionIndex, subscriptionInfo);

        // delete match
        if (err == CHIP_NO_ERROR)
        {
            if ((nodeId == subscriptionInfo.mNodeId) && (fabricIndex == subscriptionInfo.mFabricIndex) &&
                (subscriptionId == subscriptionInfo.mSubscriptionId))
            {
                subscriptionFound    = true;
                CHIP_ERROR deleteErr = Delete(subscriptionIndex);
                if (deleteErr != CHIP_NO_ERROR)
                {
                    lastDeleteErr = deleteErr;
                }
            }
            else
            {
                remainingSubscriptionsCount++;
            }
        }
    }

    // if there are no persisted subscriptions, the MaxCount can also be deleted
    if (remainingSubscriptionsCount == 0)
    {
        DeleteMaxCount();
    }

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

    return subscriptionFound ? CHIP_NO_ERROR : CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::DeleteMaxCount()
{
    return mStorage->SyncDeleteKeyValue(DefaultStorageKeyAllocator::SubscriptionResumptionMaxCount().KeyName());
}

CHIP_ERROR SimpleSubscriptionResumptionStorage::DeleteAll(FabricIndex fabricIndex)
{
    CHIP_ERROR deleteErr = CHIP_NO_ERROR;

    uint16_t count = 0;
    for (uint16_t subscriptionIndex = 0; subscriptionIndex < CHIP_IM_MAX_NUM_SUBSCRIPTIONS; subscriptionIndex++)
    {
        SubscriptionInfo subscriptionInfo;
        CHIP_ERROR err = Load(subscriptionIndex, subscriptionInfo);

        if (err == CHIP_NO_ERROR)
        {
            if (fabricIndex == subscriptionInfo.mFabricIndex)
            {
                err = Delete(subscriptionIndex);
                if ((err != CHIP_NO_ERROR) && (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
                {
                    deleteErr = err;
                }
            }
            else
            {
                count++;
            }
        }
    }

    // if there are no persisted subscriptions, the MaxCount can also be deleted
    if (count == 0)
    {
        CHIP_ERROR err = DeleteMaxCount();

        if ((err != CHIP_NO_ERROR) && (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
        {
            deleteErr = err;
        }
    }

    return deleteErr;
}

} // namespace app
} // namespace chip
