/*
 *
 *    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 "ExampleAccessControlDelegate.h"

#include <lib/core/CHIPConfig.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/DefaultStorageKeyAllocator.h>

#include <algorithm>
#include <cstdint>
#include <string>
#include <type_traits>

namespace {

using chip::ClusterId;
using chip::DeviceTypeId;
using chip::EndpointId;
using chip::FabricIndex;
using chip::NodeId;

using chip::kUndefinedNodeId;

using chip::Access::AccessControl;
using chip::Access::AuthMode;
using chip::Access::Privilege;
using chip::Access::RequestPath;
using chip::Access::SubjectDescriptor;

using Entry         = chip::Access::AccessControl::Entry;
using EntryIterator = chip::Access::AccessControl::EntryIterator;
using Target        = Entry::Target;

// Pool sizes
constexpr int kEntryStoragePoolSize          = CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_ENTRY_STORAGE_POOL_SIZE;
constexpr int kEntryDelegatePoolSize         = CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_ENTRY_DELEGATE_POOL_SIZE;
constexpr int kEntryIteratorDelegatePoolSize = CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_ENTRY_ITERATOR_DELEGATE_POOL_SIZE;

/*
              +---+   +---+   +---+   +---+
              | 1 |   | 2 |   | A |   | C |             ENTRIES
              +---+   +---+   +---+   +---+
                 |      |       |       |
                 |      +-+   +-+       |
                 +----+   |   |   +-----+
                      |   |   |   |
                      v   v   v   v
                    +---+---+---+---+
                    | 1 | 2 | A | C |                   ENTRY DELEGATE POOL
                    +---+---+---+---+
                      |   |   |   |
          +-----------+   |   |   +-----------+
          |   +-----------+   +-------+       |
          |   |                       |       |
          v   v                       v       v
    +---+---+---+---+               +---+---+---+---+
    | 0 | 1 | 2 | X |               | A | X | C | X |   ACL ENTRY STORAGE & POOL
    +---+---+---+---+               +---+---+---+---+
      ^       ^
      |       |
      |       +-----------+
      +---------------+   |
                      |   |
                    +---+---+---+---+
                    | 0 | 2 | X | X |                   ENTRY ITERATOR DELEGATE POOL
                    +---+---+---+---+
                      ^   ^
                      |   |
                      |   +-------+
                      |           |
                    +---+       +---+
                    | 0 |       | 2 |                   ENTRY ITERATORS
                    +---+       +---+
*/

class SubjectStorage
{
public:
    bool IsEmpty() const { return mNode == kUndefinedNodeId; }

    void Clear() { mNode = kUndefinedNodeId; }

    CHIP_ERROR Get(NodeId & node) const
    {
        if (!IsEmpty())
        {
            node = mNode;
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR Set(NodeId node)
    {
        if (!IsEmpty())
        {
            if (IsValid(node))
            {
                mNode = node;
                return CHIP_NO_ERROR;
            }
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR Add(NodeId node)
    {
        if (IsValid(node))
        {
            mNode = node;
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

public:
    CHIP_ERROR Serialize(chip::TLV::TLVWriter & writer) const { return writer.Put(chip::TLV::AnonymousTag(), mNode); }

    CHIP_ERROR Deserialize(chip::TLV::TLVReader & reader)
    {
        ReturnErrorOnFailure(reader.Next(chip::TLV::AnonymousTag()));
        return reader.Get(mNode);
    }

private:
    static bool IsValid(NodeId node) { return node != kUndefinedNodeId; }

private:
    static_assert(sizeof(NodeId) == 8, "Expecting 8 byte node ID");

private:
    NodeId mNode;
};

class TargetStorage
{
public:
    bool IsEmpty() const { return mCluster == kClusterEmpty && mDeviceType == kDeviceTypeEmpty; }

    void Clear()
    {
        mCluster    = kClusterEmpty;
        mDeviceType = kDeviceTypeEmpty;
    }

    CHIP_ERROR Get(Target & target) const
    {
        if (!IsEmpty())
        {
            Decode(target);
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR Set(const Target & target)
    {
        if (!IsEmpty())
        {
            if (IsValid(target))
            {
                Encode(target);
                return CHIP_NO_ERROR;
            }
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR Add(const Target & target)
    {
        if (IsValid(target))
        {
            Encode(target);
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

public:
    CHIP_ERROR Serialize(chip::TLV::TLVWriter & writer) const
    {
        ReturnErrorOnFailure(writer.Put(chip::TLV::AnonymousTag(), mCluster));
        return writer.Put(chip::TLV::AnonymousTag(), mDeviceType);
    }

    CHIP_ERROR Deserialize(chip::TLV::TLVReader & reader)
    {
        ReturnErrorOnFailure(reader.Next(chip::TLV::AnonymousTag()));
        ReturnErrorOnFailure(reader.Get(mCluster));
        ReturnErrorOnFailure(reader.Next(chip::TLV::AnonymousTag()));
        return reader.Get(mDeviceType);
    }

private:
    // TODO: eventually this functionality should live where the type itself is defined
    static bool IsValidCluster(ClusterId cluster)
    {
        const auto id     = cluster & kClusterIdMask;
        const auto vendor = cluster & kClusterVendorMask;
        return ((id <= kClusterIdMaxStd) || (kClusterIdMinMs <= id && id <= kClusterIdMaxMs)) && (vendor <= kClusterVendorMax);
    }

    // TODO: eventually this functionality should live where the type itself is defined
    static constexpr bool IsValidEndpoint(EndpointId endpoint) { return true; }

    // TODO: eventually this functionality should live where the type itself is defined
    static bool IsValidDeviceType(DeviceTypeId deviceType)
    {
        const auto id     = deviceType & kDeviceTypeIdMask;
        const auto vendor = deviceType & kDeviceTypeVendorMask;
        return (id <= kDeviceTypeIdMax) && (vendor <= kDeviceTypeVendorMax);
    }

    // TODO: eventually this functionality should live where the type itself is defined
    static bool IsValid(const Target & target)
    {
        constexpr Target::Flags kNotAll     = Target::kEndpoint | Target::kDeviceType;
        constexpr Target::Flags kAtLeastOne = kNotAll | Target::kCluster;
        constexpr Target::Flags kNone       = ~kAtLeastOne;
        return ((target.flags & kNone) == 0) && ((target.flags & kAtLeastOne) != 0) && ((target.flags & kNotAll) != kNotAll) &&
            !((target.flags & Target::kCluster) && !IsValidCluster(target.cluster)) &&
            !((target.flags & Target::kEndpoint) && !IsValidEndpoint(target.endpoint)) &&
            !((target.flags & Target::kDeviceType) && !IsValidDeviceType(target.deviceType));
    }

private:
    void Decode(Target & target) const
    {
        auto & flags      = target.flags;
        auto & cluster    = target.cluster;
        auto & endpoint   = target.endpoint;
        auto & deviceType = target.deviceType;
        flags             = 0;
        if (mCluster != kClusterEmpty)
        {
            cluster = mCluster;
            flags |= Target::kCluster;
        }
        if (mDeviceType != kDeviceTypeEmpty)
        {
            if ((mDeviceType & kDeviceTypeIdMask) == kEndpointMagic)
            {
                endpoint = static_cast<EndpointId>(mDeviceType >> kEndpointShift);
                flags |= Target::kEndpoint;
            }
            else
            {
                deviceType = mDeviceType;
                flags |= Target::kDeviceType;
            }
        }
    }

    void Encode(const Target & target)
    {
        const auto flags      = target.flags;
        const auto cluster    = target.cluster;
        const auto endpoint   = target.endpoint;
        const auto deviceType = target.deviceType;
        if (flags & Target::kCluster)
        {
            mCluster = cluster;
        }
        else
        {
            mCluster = kClusterEmpty;
        }
        if (flags & Target::kEndpoint)
        {
            mDeviceType = (static_cast<DeviceTypeId>(endpoint) << kEndpointShift) | kEndpointMagic;
        }
        else if (flags & Target::kDeviceType)
        {
            mDeviceType = deviceType;
        }
        else
        {
            mDeviceType = kDeviceTypeEmpty;
        }
    }

private:
    static_assert(sizeof(ClusterId) == 4, "Expecting 4 byte cluster ID");
    static_assert(sizeof(EndpointId) == 2, "Expecting 2 byte endpoint ID");
    static_assert(sizeof(DeviceTypeId) == 4, "Expecting 4 byte device type ID");

    // TODO: some (not all) of these values should live where the type itself is defined

    // (mCluster == kClusterEmpty) --> mCluster contains no cluster
    static constexpr ClusterId kClusterEmpty = 0xFFFFFFFF;

    // (mCluster & kClusterIdMask) --> cluster id portion
    static constexpr ClusterId kClusterIdMask = 0x0000FFFF;

    // ((mCluster & kClusterIdMask) < kClusterIdMaxStd) --> invalid
    static constexpr ClusterId kClusterIdMaxStd = 0x00007FFF;

    // ((mCluster & kClusterIdMask) < kClusterIdMinMs) --> invalid
    static constexpr ClusterId kClusterIdMinMs = 0x0000FC00;

    // ((mCluster & kClusterIdMask) < kClusterIdMaxMs) --> invalid
    static constexpr ClusterId kClusterIdMaxMs = 0x0000FFFE;

    // (mCluster & kClusterVendorMask) --> cluster vendor portion
    static constexpr ClusterId kClusterVendorMask = 0xFFFF0000;

    // ((mCluster & kClusterVendorMask) > kClusterVendorMax) --> invalid
    static constexpr ClusterId kClusterVendorMax = 0xFFFE0000;

    // (mDeviceType == kDeviceTypeEmpty) --> mDeviceType contains neither endpoint nor device type
    static constexpr DeviceTypeId kDeviceTypeEmpty = 0xFFFFFFFF;

    // (mDeviceType & kDeviceTypeIdMask) --> device type id portion
    static constexpr DeviceTypeId kDeviceTypeIdMask = 0x0000FFFF;

    // ((mDeviceType & kDeviceTypeIdMask) < kDeviceTypeIdMax) --> invalid
    static constexpr DeviceTypeId kDeviceTypeIdMax = 0x0000BFFF;

    // (mDeviceType & kDeviceTypeVendorMask) --> device type vendor portion
    static constexpr DeviceTypeId kDeviceTypeVendorMask = 0xFFFF0000;

    // ((mDeviceType & kDeviceTypeVendorMask) > kDeviceTypeVendorMax) --> invalid
    static constexpr DeviceTypeId kDeviceTypeVendorMax = 0xFFFE0000;

    // ((mDeviceType & kDeviceTypeIdMask) == kEndpointMagic) --> mDeviceType contains endpoint
    static constexpr DeviceTypeId kEndpointMagic = 0x0000EEEE;

    // (mDeviceType >> kEndpointShift) --> extract endpoint from mDeviceType
    static constexpr int kEndpointShift = 16;

private:
    ClusterId mCluster;
    DeviceTypeId mDeviceType;
};

class EntryStorage
{
public:
    // ACL support
    static constexpr size_t kNumberOfFabrics  = CHIP_CONFIG_MAX_FABRICS;
    static constexpr size_t kEntriesPerFabric = CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC;
    static EntryStorage acl[kNumberOfFabrics * kEntriesPerFabric];

    // Find the next unused entry storage in the access control list, if one exists.
    static EntryStorage * FindUnusedInAcl()
    {
        for (auto & storage : acl)
        {
            if (!storage.InUse())
            {
                return &storage;
            }
        }
        return nullptr;
    }

    // Find the specified used entry storage in the access control list, if it exists.
    static EntryStorage * FindUsedInAcl(size_t index, const FabricIndex * fabricIndex)
    {
        if (fabricIndex != nullptr)
        {
            ConvertIndex(index, *fabricIndex, ConvertDirection::kRelativeToAbsolute);
        }
        if (index < ArraySize(acl))
        {
            auto * storage = acl + index;
            if (storage->InUse())
            {
                return storage;
            }
        }
        return nullptr;
    }

public:
    // Pool support
    static EntryStorage pool[kEntryStoragePoolSize];

    // Find an unused entry storage in the pool, if one is available.
    // The candidate is preferred if provided and it is in the pool,
    // regardless of whether it is already in use.
    static EntryStorage * Find(EntryStorage * candidate)
    {
        if (candidate && candidate->InPool())
        {
            return candidate;
        }
        for (auto & storage : pool)
        {
            if (!storage.InUse())
            {
                return &storage;
            }
        }
        return nullptr;
    }

    bool InPool() const
    {
        constexpr auto * end = pool + ArraySize(pool);
        return pool <= this && this < end;
    }

public:
    EntryStorage() = default;

    void Init()
    {
        if (!mInUse)
        {
            Clear();
            mInUse = true;
        }
    }

    bool InUse() const { return mInUse; }

    void Release()
    {
        if (InPool())
        {
            mInUse = false;
        }
    }

    void Clear()
    {
        mInUse       = false;
        mFabricIndex = chip::kUndefinedFabricIndex;
        mAuthMode    = AuthMode::kPase;
        mPrivilege   = Privilege::kView;
        for (auto & subject : mSubjects)
        {
            subject.Clear();
        }
        for (auto & target : mTargets)
        {
            target.Clear();
        }
    }

public:
    enum class ConvertDirection
    {
        kAbsoluteToRelative,
        kRelativeToAbsolute
    };

    // Entries have a position in the access control list, denoted by an "absolute" index.
    // Because entries are scoped to a fabric, a "fabric relative" index can be inferred.
    //
    // For example: suppose there are 8 entries for fabrics A, B, and C (as fabric indexes 1, 2, 3).
    //
    //        0   1   2   3   4   5   6   7     ABSOLUTE INDEX
    //      +---+---+---+---+---+---+---+---+
    //      | A0| A1| B0| A2| B1| B2| C0| C1|   FABRIC RELATIVE INDEX
    //      +---+---+---+---+---+---+---+---+
    //
    // While the entry at (absolute) index 2 is the third entry, it is the first entry scoped to
    // fabric B. So relative to fabric index 2, the entry is at (relative) index 0.
    //
    // The opposite is true: the second entry scoped to fabric B, at (relative) index 1, is the
    // fifth entry overall, at (absolute) index 4.
    //
    // Not all conversions are possible. For example, absolute index 3 is not scoped to fabric B, so
    // attempting to convert it to be relative to fabric index 2 will fail. Likewise, fabric B does
    // not contain a fourth entry, so attempting to convert index 3 (relative to fabric index 2) to
    // an absolute index will also fail. Such failures are denoted by use of an index that is one
    // past the end of the access control list. (So in this example, failure produces index 8.)
    static void ConvertIndex(size_t & index, const FabricIndex fabricIndex, ConvertDirection direction)
    {
        size_t absoluteIndex = 0;
        size_t relativeIndex = 0;
        size_t & fromIndex   = (direction == ConvertDirection::kAbsoluteToRelative) ? absoluteIndex : relativeIndex;
        size_t & toIndex     = (direction == ConvertDirection::kAbsoluteToRelative) ? relativeIndex : absoluteIndex;
        bool found           = false;
        for (const auto & storage : acl)
        {
            if (!storage.InUse())
            {
                break;
            }
            if (storage.mFabricIndex == fabricIndex)
            {
                if (index == fromIndex)
                {
                    found = true;
                    break;
                }
                relativeIndex++;
            }
            absoluteIndex++;
        }
        index = found ? toIndex : ArraySize(acl);
    }

public:
    static constexpr uint8_t kTagInUse       = 1;
    static constexpr uint8_t kTagFabricIndex = 2;
    static constexpr uint8_t kTagAuthMode    = 3;
    static constexpr uint8_t kTagPrivilege   = 4;
    static constexpr uint8_t kTagSubjects    = 5;
    static constexpr uint8_t kTagTargets     = 6;

    CHIP_ERROR Serialize(chip::PersistentStorageDelegate * storage, const char * key)
    {
        uint8_t buffer[kStorageBufferSize] = { 0 };
        chip::TLV::TLVWriter writer;
        writer.Init(buffer);
        chip::TLV::TLVType container;
        ReturnErrorOnFailure(writer.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::TLVType::kTLVType_Structure, container));

        ReturnErrorOnFailure(writer.Put(chip::TLV::ContextTag(kTagInUse), mInUse));
        ReturnErrorOnFailure(writer.Put(chip::TLV::ContextTag(kTagFabricIndex), mFabricIndex));
        ReturnErrorOnFailure(writer.Put(chip::TLV::ContextTag(kTagAuthMode), mAuthMode));
        ReturnErrorOnFailure(writer.Put(chip::TLV::ContextTag(kTagPrivilege), mPrivilege));

        chip::TLV::TLVType internalContainer;
        ReturnErrorOnFailure(
            writer.StartContainer(chip::TLV::ContextTag(kTagSubjects), chip::TLV::TLVType::kTLVType_Array, internalContainer));
        for (size_t i = 0; i < kMaxSubjects; ++i)
        {
            ReturnErrorOnFailure(mSubjects[i].Serialize(writer));
        }
        ReturnErrorOnFailure(writer.EndContainer(internalContainer));

        ReturnErrorOnFailure(
            writer.StartContainer(chip::TLV::ContextTag(kTagTargets), chip::TLV::TLVType::kTLVType_Array, internalContainer));
        for (size_t i = 0; i < kMaxTargets; ++i)
        {
            ReturnErrorOnFailure(mTargets[i].Serialize(writer));
        }
        ReturnErrorOnFailure(writer.EndContainer(internalContainer));

        ReturnErrorOnFailure(writer.EndContainer(container));
        ReturnErrorOnFailure(writer.Finalize());

        return storage->SyncSetKeyValue(key, buffer, static_cast<uint16_t>(writer.GetLengthWritten()));
    }

    CHIP_ERROR Deserialize(chip::PersistentStorageDelegate * storage, const char * key)
    {
        uint8_t buffer[kStorageBufferSize] = { 0 };
        uint16_t bufferSize                = static_cast<uint16_t>(sizeof(buffer));
        ReturnErrorOnFailure(storage->SyncGetKeyValue(key, buffer, bufferSize));
        chip::TLV::TLVReader reader;
        reader.Init(buffer, bufferSize);

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

        chip::TLV::TLVType container;
        ReturnErrorOnFailure(reader.EnterContainer(container));

        ReturnErrorOnFailure(reader.Next(chip::TLV::ContextTag(kTagInUse)));
        ReturnErrorOnFailure(reader.Get(mInUse));
        ReturnErrorOnFailure(reader.Next(chip::TLV::ContextTag(kTagFabricIndex)));
        ReturnErrorOnFailure(reader.Get(mFabricIndex));
        ReturnErrorOnFailure(reader.Next(chip::TLV::ContextTag(kTagAuthMode)));
        ReturnErrorOnFailure(reader.Get(mAuthMode));
        ReturnErrorOnFailure(reader.Next(chip::TLV::ContextTag(kTagPrivilege)));
        ReturnErrorOnFailure(reader.Get(mPrivilege));

        chip::TLV::TLVType innerContainer;
        ReturnErrorOnFailure(reader.Next(chip::TLV::TLVType::kTLVType_Array, chip::TLV::ContextTag(kTagSubjects)));
        ReturnErrorOnFailure(reader.EnterContainer(innerContainer));
        for (size_t i = 0; i < kMaxSubjects; ++i)
        {
            ReturnErrorOnFailure(mSubjects[i].Deserialize(reader));
        }
        ReturnErrorOnFailure(reader.ExitContainer(innerContainer));

        ReturnErrorOnFailure(reader.Next(chip::TLV::TLVType::kTLVType_Array, chip::TLV::ContextTag(kTagTargets)));
        ReturnErrorOnFailure(reader.EnterContainer(innerContainer));
        for (size_t i = 0; i < kMaxTargets; ++i)
        {
            ReturnErrorOnFailure(mTargets[i].Deserialize(reader));
        }
        ReturnErrorOnFailure(reader.ExitContainer(innerContainer));

        return reader.ExitContainer(container);
    }

public:
    static constexpr size_t kMaxSubjects = CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY;
    static constexpr size_t kMaxTargets  = CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY;

    static constexpr uint8_t kApproxSizeSubject = 9;
    static constexpr uint8_t kApproxSizeTarget  = 8;
    static constexpr uint8_t kApproxSizeEntry   = 4;
    // This value was chosen to be large enough to contain the data, but has not been fine-tuned.
    static const size_t kStorageBufferSize =
        kEntriesPerFabric * (kApproxSizeEntry + kApproxSizeSubject * kMaxSubjects + kApproxSizeTarget * kMaxTargets);

    bool mInUse;
    FabricIndex mFabricIndex;
    AuthMode mAuthMode;
    Privilege mPrivilege;
    SubjectStorage mSubjects[kMaxSubjects];
    TargetStorage mTargets[kMaxTargets];
};

class EntryDelegate : public Entry::Delegate
{
public:
    // Pool support
    static EntryDelegate pool[kEntryDelegatePoolSize];

    // Find an unused entry delegate in the pool, if one is available.
    // The candidate is preferred if it is in the pool, regardless of whether
    // it is already in use.
    static EntryDelegate * Find(Entry::Delegate & candidate)
    {
        if (InPool(candidate))
        {
            return &static_cast<EntryDelegate &>(candidate);
        }
        for (auto & delegate : pool)
        {
            if (!delegate.InUse())
            {
                return &delegate;
            }
        }
        return nullptr;
    }

    static bool InPool(const Entry::Delegate & delegate)
    {
        constexpr auto * end = pool + ArraySize(pool);
        return pool <= &delegate && &delegate < end;
    }

public:
    void Release() override
    {
        mStorage->Release();
        mStorage = nullptr;
    }

    CHIP_ERROR GetAuthMode(AuthMode & authMode) const override
    {
        authMode = mStorage->mAuthMode;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetFabricIndex(FabricIndex & fabricIndex) const override
    {
        fabricIndex = mStorage->mFabricIndex;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetPrivilege(Privilege & privilege) const override
    {
        privilege = mStorage->mPrivilege;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR SetAuthMode(AuthMode authMode) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        mStorage->mAuthMode = authMode;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR SetFabricIndex(FabricIndex fabricIndex) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        mStorage->mFabricIndex = fabricIndex;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR SetPrivilege(Privilege privilege) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        mStorage->mPrivilege = privilege;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSubjectCount(size_t & count) const override
    {
        count = 0;
        for (const auto & subject : mStorage->mSubjects)
        {
            if (subject.IsEmpty())
            {
                break;
            }
            count++;
        }
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSubject(size_t index, NodeId & subject) const override
    {
        if (index < EntryStorage::kMaxSubjects)
        {
            return mStorage->mSubjects[index].Get(subject);
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR SetSubject(size_t index, NodeId subject) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        if (index < EntryStorage::kMaxSubjects)
        {
            return mStorage->mSubjects[index].Set(subject);
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR AddSubject(size_t * index, NodeId subject) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        size_t count = 0;
        GetSubjectCount(count);
        if (count < EntryStorage::kMaxSubjects)
        {
            CHIP_ERROR err = mStorage->mSubjects[count].Add(subject);
            if (err == CHIP_NO_ERROR && index != nullptr)
            {
                *index = count;
            }
            return err;
        }
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    CHIP_ERROR RemoveSubject(size_t index) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        size_t count = 0;
        GetSubjectCount(count);
        if (index < count)
        {
            // The storage at the specified index will be deleted by copying any subsequent storage
            // over it, ideally also including one unused storage past the ones in use. If all
            // storage was in use, this isn't possible, so the final storage is manually cleared.
            auto * dest      = mStorage->mSubjects + index;
            const auto * src = dest + 1;
            const auto n     = std::min(count, EntryStorage::kMaxSubjects - 1) - index;
            memmove(dest, src, n * sizeof(*dest));
            if (count == EntryStorage::kMaxSubjects)
            {
                mStorage->mSubjects[EntryStorage::kMaxSubjects - 1].Clear();
            }
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR GetTargetCount(size_t & count) const override
    {
        count = 0;
        for (const auto & target : mStorage->mTargets)
        {
            if (target.IsEmpty())
            {
                break;
            }
            count++;
        }
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetTarget(size_t index, Target & target) const override
    {
        if (index < EntryStorage::kMaxTargets)
        {
            return mStorage->mTargets[index].Get(target);
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR SetTarget(size_t index, const Target & target) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        if (index < EntryStorage::kMaxTargets)
        {
            return mStorage->mTargets[index].Set(target);
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR AddTarget(size_t * index, const Target & target) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        size_t count = 0;
        GetTargetCount(count);
        if (count < EntryStorage::kMaxTargets)
        {
            CHIP_ERROR err = mStorage->mTargets[count].Add(target);
            if (err == CHIP_NO_ERROR && index != nullptr)
            {
                *index = count;
            }
            return err;
        }
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    CHIP_ERROR RemoveTarget(size_t index) override
    {
        ReturnErrorOnFailure(EnsureStorageInPool());
        size_t count = 0;
        GetTargetCount(count);
        if (index < count)
        {
            // The storage at the specified index will be deleted by copying any subsequent storage
            // over it, ideally also including one unused storage past the ones in use. If all
            // storage was in use, this isn't possible, so the final storage is manually cleared.
            auto * dest      = mStorage->mTargets + index;
            const auto * src = dest + 1;
            const auto n     = std::min(count, EntryStorage::kMaxTargets - 1) - index;
            memmove(dest, src, n * sizeof(*dest));
            if (count == EntryStorage::kMaxTargets)
            {
                mStorage->mTargets[EntryStorage::kMaxTargets - 1].Clear();
            }
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

public:
    void Init(Entry & entry, EntryStorage & storage)
    {
        entry.SetDelegate(*this);
        storage.Init();
        mEntry   = &entry;
        mStorage = &storage;
    }

    bool InUse() const { return mStorage != nullptr; }

    const EntryStorage * GetStorage() const { return mStorage; }

    EntryStorage * GetStorage() { return mStorage; }

    void FixAfterDelete(EntryStorage & storage)
    {
        constexpr auto & acl = EntryStorage::acl;
        constexpr auto * end = acl + ArraySize(acl);
        if (mStorage == &storage)
        {
            mEntry->ResetDelegate();
        }
        else if (&storage < mStorage && mStorage < end)
        {
            mStorage--;
        }
    }

    // Ensure the delegate is using storage from the pool (not the access control list),
    // by copying (from the access control list to the pool) if necessary.
    CHIP_ERROR EnsureStorageInPool()
    {
        if (mStorage->InPool())
        {
            return CHIP_NO_ERROR;
        }
        if (auto * storage = EntryStorage::Find(nullptr))
        {
            *storage = *mStorage;
            mStorage = storage;
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

private:
    Entry * mEntry          = nullptr;
    EntryStorage * mStorage = nullptr;
};

class EntryIteratorDelegate : public EntryIterator::Delegate
{
public:
    // Pool support
    static EntryIteratorDelegate pool[kEntryIteratorDelegatePoolSize];

    // Find an unused entry iterator delegate in the pool, if one is available.
    // The candidate is preferred if it is in the pool, regardless of whether
    // it is already in use.
    static EntryIteratorDelegate * Find(EntryIterator::Delegate & candidate)
    {
        if (InPool(candidate))
        {
            return static_cast<EntryIteratorDelegate *>(&candidate);
        }
        for (auto & delegate : pool)
        {
            if (!delegate.InUse())
            {
                return &delegate;
            }
        }
        return nullptr;
    }

    static bool InPool(const EntryIterator::Delegate & delegate)
    {
        constexpr auto * end = pool + ArraySize(pool);
        return pool <= &delegate && &delegate < end;
    }

public:
    void Release() override { mInUse = false; }

    CHIP_ERROR Next(Entry & entry) override
    {
        constexpr auto & acl = EntryStorage::acl;
        constexpr auto * end = acl + ArraySize(acl);
        while (true)
        {
            if (mStorage == nullptr)
            {
                // Start at beginning of access control list...
                mStorage = acl;
            }
            else if (mStorage < end)
            {
                // ...and continue iterating entries...
                mStorage++;
            }
            if (mStorage == end || !mStorage->InUse())
            {
                // ...but only used ones...
                mStorage = end;
                break;
            }
            if (mFabricFiltered && mStorage->mFabricIndex != mFabricIndex)
            {
                // ...skipping those that aren't scoped to a specified fabric...
                continue;
            }
            if (auto * delegate = EntryDelegate::Find(entry.GetDelegate()))
            {
                // ...returning any next entry via a delegate.
                delegate->Init(entry, *mStorage);
                return CHIP_NO_ERROR;
            }
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        return CHIP_ERROR_SENTINEL;
    }

public:
    void Init(EntryIterator & iterator, const FabricIndex * fabricIndex)
    {
        iterator.SetDelegate(*this);
        mInUse          = true;
        mFabricFiltered = fabricIndex != nullptr;
        if (mFabricFiltered)
        {
            mFabricIndex = *fabricIndex;
        }
        mStorage = nullptr;
    }

    bool InUse() const { return mInUse; }

    void FixAfterDelete(EntryStorage & storage)
    {
        constexpr auto & acl = EntryStorage::acl;
        constexpr auto * end = acl + ArraySize(acl);
        if (&storage <= mStorage && mStorage < end)
        {
            if (mStorage == acl)
            {
                mStorage = nullptr;
            }
            else
            {
                mStorage--;
            }
        }
    }

private:
    bool mInUse = false;
    bool mFabricFiltered;
    FabricIndex mFabricIndex;
    EntryStorage * mStorage;
};

CHIP_ERROR CopyViaInterface(const Entry & entry, EntryStorage & storage)
{
#if CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_FLEXIBLE_COPY_SUPPORT
    // NOTE: uses sizeof(EntryStorage) on stack as a temporary and is only necessary if using this
    //       file with other Entry::Delegate implementations that are not EntryDelegate in this file
    EntryStorage temp;
    temp.Clear();

    FabricIndex fabricIndex = kUndefinedFabricIndex;
    ReturnErrorOnFailure(entry.GetFabricIndex(fabricIndex));
    temp.mFabricIndex = fabricIndex;

    AuthMode authMode = AuthMode::kNone;
    ReturnErrorOnFailure(entry.GetAuthMode(authMode));
    temp.mAuthMode = authMode;

    Privilege privilege = Privilege::kView;
    ReturnErrorOnFailure(entry.GetPrivilege(privilege));
    temp.mPrivilege = privilege;

    size_t subjectCount = 0;
    ReturnErrorOnFailure(entry.GetSubjectCount(subjectCount));
    ReturnErrorCodeIf(subjectCount > EntryStorage::kMaxSubjects, CHIP_ERROR_BUFFER_TOO_SMALL);
    for (size_t i = 0; i < subjectCount; ++i)
    {
        NodeId subject = kUndefinedNodeId;
        ReturnErrorOnFailure(entry.GetSubject(i, subject));
        temp.mSubjects[i].Add(subject);
    }

    size_t targetCount = 0;
    ReturnErrorOnFailure(entry.GetTargetCount(targetCount));
    ReturnErrorCodeIf(targetCount > EntryStorage::kMaxTargets, CHIP_ERROR_BUFFER_TOO_SMALL);
    for (size_t i = 0; i < targetCount; ++i)
    {
        Target target;
        ReturnErrorOnFailure(entry.GetTarget(i, target));
        temp.mTargets[i].Add(target);
    }

    temp.mInUse = true;
    storage     = temp;
    return CHIP_NO_ERROR;
#else
    // NOTE: save space by not implementing function
    VerifyOrDie(false);
    return CHIP_ERROR_NOT_IMPLEMENTED;
#endif
}

CHIP_ERROR Copy(const Entry & entry, EntryStorage & storage)
{
#if CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_FAST_COPY_SUPPORT
    auto & delegate = entry.GetDelegate();
    if (EntryDelegate::InPool(delegate))
    {
        // NOTE: if an entry's delegate is in the pool, it must be an EntryDelegate,
        //       which must have a storage that is in use, which can be copied as POD
        storage = *static_cast<const EntryDelegate &>(delegate).GetStorage();
        return CHIP_NO_ERROR;
    }
#endif
    return CopyViaInterface(entry, storage);
}

class AccessControlDelegate : public AccessControl::Delegate
{
public:
    CHIP_ERROR Init() override
    {
        ChipLogProgress(DataManagement, "Examples::AccessControlDelegate::Init");
        CHIP_ERROR err = LoadFromFlash();
        if (err != CHIP_NO_ERROR)
        {
            ChipLogProgress(DataManagement, "AccessControl: unable to load stored ACL entries; using empty list instead");
            for (auto & storage : EntryStorage::acl)
            {
                storage.Clear();
            }
        }
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR Finish() override
    {
        ChipLogProgress(DataManagement, "Examples::AccessControlDelegate::Finish");
        return SaveToFlash();
    }

    CHIP_ERROR GetMaxEntryCount(size_t & value) const override
    {
        value = ArraySize(EntryStorage::acl);
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetEntryCount(size_t & value) const override
    {
        value = 0;
        for (const auto & storage : EntryStorage::acl)
        {
            if (!storage.InUse())
            {
                break;
            }
            value++;
        }
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR PrepareEntry(Entry & entry) override
    {
        if (auto * delegate = EntryDelegate::Find(entry.GetDelegate()))
        {
            if (auto * storage = EntryStorage::Find(delegate->GetStorage()))
            {
                delegate->Init(entry, *storage);
                return CHIP_NO_ERROR;
            }
        }
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    CHIP_ERROR CreateEntry(size_t * index, const Entry & entry, FabricIndex * fabricIndex) override
    {
        if (auto * storage = EntryStorage::FindUnusedInAcl())
        {
            CHIP_ERROR err = Copy(entry, *storage);
            if (err == CHIP_NO_ERROR)
            {
                if (fabricIndex != nullptr)
                {
                    *fabricIndex = storage->mFabricIndex;
                }
                if (index != nullptr)
                {
                    *index = size_t(storage - EntryStorage::acl);
                    if (fabricIndex != nullptr)
                    {
                        EntryStorage::ConvertIndex(*index, *fabricIndex, EntryStorage::ConvertDirection::kAbsoluteToRelative);
                    }
                }

                CHIP_ERROR saveError = SaveToFlash();
                if (saveError != CHIP_NO_ERROR && saveError != CHIP_ERROR_INCORRECT_STATE)
                {
                    ChipLogProgress(DataManagement, "CreateEntry failed to save to flash");
                }
            }
            return err;
        }
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    CHIP_ERROR ReadEntry(size_t index, Entry & entry, const FabricIndex * fabricIndex) const override
    {
        if (auto * storage = EntryStorage::FindUsedInAcl(index, fabricIndex))
        {
            if (auto * delegate = EntryDelegate::Find(entry.GetDelegate()))
            {
                delegate->Init(entry, *storage);
                return CHIP_NO_ERROR;
            }
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR UpdateEntry(size_t index, const Entry & entry, const FabricIndex * fabricIndex) override
    {
        if (auto * storage = EntryStorage::FindUsedInAcl(index, fabricIndex))
        {
            CHIP_ERROR err = Copy(entry, *storage);
            if (err == CHIP_NO_ERROR)
            {
                CHIP_ERROR saveError = SaveToFlash();
                if (saveError != CHIP_NO_ERROR && saveError != CHIP_ERROR_INCORRECT_STATE)
                {
                    ChipLogProgress(DataManagement, "UpdateEntry failed to save to flash");
                }
            }
            return err;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR DeleteEntry(size_t index, const FabricIndex * fabricIndex) override
    {
        if (auto * storage = EntryStorage::FindUsedInAcl(index, fabricIndex))
        {
            constexpr auto & acl = EntryStorage::acl;
            constexpr auto * end = acl + ArraySize(acl);
            // Go through the access control list starting at the deleted storage...
            for (auto * next = storage + 1; storage < end; ++storage, ++next)
            {
                // ...copying over each storage with its next one...
                if (next < end && next->InUse())
                {
                    *storage = *next;
                }
                else
                {
                    // ...clearing the last previously used one...
                    storage->Clear();
                    break;
                }
            }
            // ...then fix up all the delegates so they still use the proper storage.
            storage = acl + index;
            for (auto & delegate : EntryDelegate::pool)
            {
                delegate.FixAfterDelete(*storage);
            }
            for (auto & delegate : EntryIteratorDelegate::pool)
            {
                delegate.FixAfterDelete(*storage);
            }

            CHIP_ERROR saveError = SaveToFlash();
            if (saveError != CHIP_NO_ERROR && saveError != CHIP_ERROR_INCORRECT_STATE)
            {
                ChipLogProgress(DataManagement, "DeleteEntry failed to save to flash");
            }
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR Entries(EntryIterator & iterator, const FabricIndex * fabricIndex) const override
    {
        if (auto * delegate = EntryIteratorDelegate::Find(iterator.GetDelegate()))
        {
            delegate->Init(iterator, fabricIndex);
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath,
                     Privilege requestPrivilege) override
    {
        return CHIP_ERROR_NOT_IMPLEMENTED;
    }

public:
    void SetStorageDelegate(chip::PersistentStorageDelegate * storageDelegate) { mStorageDelegate = storageDelegate; }

private:
    chip::PersistentStorageDelegate * mStorageDelegate = nullptr;

    // The version of the storage data format. Increment this key when the format of the data model changes.
    static const uint32_t kExampleAclStorageVersion = 1;
    // This value was chosen to be large enough to contain the data, but has not been fine-tuned.
    static const size_t kStorageBufferSize = 32;
    static constexpr uint8_t kTagVersion   = 1;

    CHIP_ERROR LoadFromFlash()
    {
        VerifyOrReturnError(mStorageDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);

        uint8_t buffer[kStorageBufferSize] = { 0 };
        uint16_t size                      = static_cast<uint16_t>(sizeof(buffer));
        chip::DefaultStorageKeyAllocator key;
        ReturnErrorOnFailure(mStorageDelegate->SyncGetKeyValue(key.AccessControlList(), buffer, size));

        chip::TLV::TLVReader reader;
        reader.Init(buffer, size);

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

        chip::TLV::TLVType container;
        ReturnErrorOnFailure(reader.EnterContainer(container));

        ReturnErrorOnFailure(reader.Next(chip::TLV::ContextTag(kTagVersion)));
        uint32_t version;
        ReturnErrorOnFailure(reader.Get(version));
        VerifyOrReturnError(version == kExampleAclStorageVersion, CHIP_ERROR_VERSION_MISMATCH);

        for (size_t i = 0; i < EntryStorage::kNumberOfFabrics * EntryStorage::kEntriesPerFabric; ++i)
        {
            ReturnErrorOnFailure(EntryStorage::acl[i].Deserialize(mStorageDelegate, key.AccessControlEntry(i)));
        }
        return reader.ExitContainer(container);
    }

    CHIP_ERROR SaveToFlash()
    {
        VerifyOrReturnError(mStorageDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);

        uint8_t buffer[kStorageBufferSize] = { 0 };
        chip::TLV::TLVWriter writer;
        writer.Init(buffer);
        chip::DefaultStorageKeyAllocator key;
        chip::TLV::TLVType container;
        ReturnErrorOnFailure(writer.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::TLVType::kTLVType_Structure, container));
        ReturnErrorOnFailure(writer.Put(chip::TLV::ContextTag(kTagVersion), kExampleAclStorageVersion));
        for (size_t i = 0; i < EntryStorage::kNumberOfFabrics * EntryStorage::kEntriesPerFabric; ++i)
        {
            ReturnErrorOnFailure(EntryStorage::acl[i].Serialize(mStorageDelegate, key.AccessControlEntry(i)));
        }
        ReturnErrorOnFailure(writer.EndContainer(container));
        ReturnErrorOnFailure(writer.Finalize());

        return mStorageDelegate->SyncSetKeyValue(key.AccessControlList(), buffer, static_cast<uint16_t>(writer.GetLengthWritten()));
    }
};

static_assert(std::is_pod<SubjectStorage>(), "Storage type must be POD");
static_assert(std::is_pod<TargetStorage>(), "Storage type must be POD");
static_assert(std::is_pod<EntryStorage>(), "Storage type must be POD");

EntryStorage EntryStorage::acl[];
EntryStorage EntryStorage::pool[];
EntryDelegate EntryDelegate::pool[];
EntryIteratorDelegate EntryIteratorDelegate::pool[];

} // namespace

namespace chip {
namespace Access {
namespace Examples {

AccessControl::Delegate * GetAccessControlDelegate(PersistentStorageDelegate * storageDelegate)
{
    static AccessControlDelegate accessControlDelegate;
    accessControlDelegate.SetStorageDelegate(storageDelegate);
    return &accessControlDelegate;
}

} // namespace Examples
} // namespace Access
} // namespace chip
