/*
 *
 *    Copyright (c) 2022 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 <app/server/DefaultAclStorage.h>

#include <lib/support/DefaultStorageKeyAllocator.h>

using namespace chip;
using namespace chip::app;
using namespace chip::Access;

using EncodableEntry   = AclStorage::EncodableEntry;
using Entry            = AccessControl::Entry;
using EntryListener    = AccessControl::EntryListener;
using StagingAuthMode  = Clusters::AccessControl::AccessControlEntryAuthModeEnum;
using StagingPrivilege = Clusters::AccessControl::AccessControlEntryPrivilegeEnum;
using StagingTarget    = Clusters::AccessControl::Structs::Target::Type;
using Target           = AccessControl::Entry::Target;

namespace {

/*
Size calculation for TLV encoded entry.

Because EncodeForWrite is used without an accessing fabric, the fabric index is
not encoded. However, let's assume it is. This yields 17 bytes total overhead,
but it's wise to add a few more for safety.

Each subject may require up to 9 bytes. Each target may require up to 14 bytes
(only one of endpoint or device type will be encoded).

DATA                                    C   T   L   V   NOTES
structure (anonymous)                   1               0x15
  field 1 privilege                     1   1       1
  field 2 authmode                      1   1       1
  field 3 subjects                      1   1
    uint64                              1           8   per subject
  end list                              1               0x18
  field 4 targets                       1   1
    structure (anonymous)               1               per target
      field 0 cluster                   1   1       4
      field 1 endpoint                  1   1       2   only field 1 or 2
      field 2 devicetype                1   1       4   only field 1 or 2
    end structure                       1
  end list                              1               0x18
  field 254 fabric index                1   1       1   not written
end structure                           1               0x18
*/

// TODO(#14455): get actual values for max subjects/targets
constexpr int kEncodedEntryOverheadBytes = 17 + 8;
constexpr int kEncodedEntrySubjectBytes  = 9 * CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY;
constexpr int kEncodedEntryTargetBytes   = 14 * CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY;
constexpr int kEncodedEntryTotalBytes    = kEncodedEntryOverheadBytes + kEncodedEntrySubjectBytes + kEncodedEntryTargetBytes;

class : public EntryListener
{
public:
    void OnEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index, const Entry * entry,
                        ChangeType changeType) override
    {
        CHIP_ERROR err;

        uint8_t buffer[kEncodedEntryTotalBytes] = { 0 };

        VerifyOrExit(mPersistentStorage != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

        if (changeType == ChangeType::kRemoved)
        {
            // Shuffle down entries past index, then delete entry at last index.
            while (true)
            {
                uint16_t size = static_cast<uint16_t>(sizeof(buffer));
                err           = mPersistentStorage->SyncGetKeyValue(
                    DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index + 1).KeyName(), buffer, size);
                if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
                {
                    break;
                }
                SuccessOrExit(err);
                SuccessOrExit(err = mPersistentStorage->SyncSetKeyValue(
                                  DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName(), buffer, size));
                index++;
            }
            SuccessOrExit(err = mPersistentStorage->SyncDeleteKeyValue(
                              DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName()));
        }
        else
        {
            // Write added/updated entry at index.
            VerifyOrExit(entry != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
            TLV::TLVWriter writer;
            writer.Init(buffer);
            EncodableEntry encodableEntry(*entry);
            SuccessOrExit(err = encodableEntry.EncodeForWrite(writer, TLV::AnonymousTag()));
            SuccessOrExit(err = mPersistentStorage->SyncSetKeyValue(
                              DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName(), buffer,
                              static_cast<uint16_t>(writer.GetLengthWritten())));
        }

        return;

    exit:
        ChipLogError(DataManagement, "DefaultAclStorage: failed %" CHIP_ERROR_FORMAT, err.Format());
    }

    // Must initialize before use.
    void Init(PersistentStorageDelegate & persistentStorage) { mPersistentStorage = &persistentStorage; }

private:
    PersistentStorageDelegate * mPersistentStorage = nullptr;

} sEntryListener;

} // namespace

namespace chip {
namespace app {

CHIP_ERROR DefaultAclStorage::Init(PersistentStorageDelegate & persistentStorage, ConstFabricIterator first,
                                   ConstFabricIterator last)
{
    ChipLogProgress(DataManagement, "DefaultAclStorage: initializing");

    CHIP_ERROR err;

    size_t count = 0;

    for (auto it = first; it != last; ++it)
    {
        auto fabric = it->GetFabricIndex();
        for (size_t index = 0; /**/; ++index)
        {
            uint8_t buffer[kEncodedEntryTotalBytes] = { 0 };
            uint16_t size                           = static_cast<uint16_t>(sizeof(buffer));
            err = persistentStorage.SyncGetKeyValue(DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName(),
                                                    buffer, size);
            if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
            {
                break;
            }
            SuccessOrExit(err);

            TLV::TLVReader reader;
            reader.Init(buffer, size);
            SuccessOrExit(err = reader.Next());

            DecodableEntry decodableEntry;
            SuccessOrExit(err = decodableEntry.Decode(reader));

            Entry & entry = decodableEntry.GetEntry();
            SuccessOrExit(err = entry.SetFabricIndex(fabric));

            SuccessOrExit(err = GetAccessControl().CreateEntry(nullptr, fabric, nullptr, entry));
            count++;
        }
    }

    ChipLogProgress(DataManagement, "DefaultAclStorage: %u entries loaded", (unsigned) count);

    sEntryListener.Init(persistentStorage);
    GetAccessControl().AddEntryListener(sEntryListener);

    return CHIP_NO_ERROR;

exit:
    ChipLogError(DataManagement, "DefaultAclStorage: failed %" CHIP_ERROR_FORMAT, err.Format());
    return err;
}

} // namespace app
} // namespace chip
