/*
 *
 *    Copyright (c) 2021 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.
 */
#pragma once

#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/CHIPMemString.h>

#include <stdio.h>

namespace chip {

/**
 * Represents a key used for addressing a specific storage element.
 *
 * May contain generic fixed keys (e.g. "g/fidx") or formatted fabric-specific
 * keys ("f/%x/..." where %x is the fabric index).
 */
class StorageKeyName
{
public:
    StorageKeyName(const StorageKeyName & other) = default;
    StorageKeyName & operator=(const StorageKeyName & other) = default;

    ~StorageKeyName() { memset(mKeyNameBuffer, 0, sizeof(mKeyNameBuffer)); }

    const char * KeyName() const { return mKeyNameBuffer; }

    bool IsInitialized() const { return mKeyNameBuffer[0] != 0; }
    bool IsUninitialized() const { return mKeyNameBuffer[0] == 0; }
    bool operator!() const { return IsUninitialized(); }

    static StorageKeyName FromConst(const char * value)
    {
        StorageKeyName result;
        Platform::CopyString(result.mKeyNameBuffer, value);
        return result;
    }

    static StorageKeyName ENFORCE_FORMAT(1, 2) Formatted(const char * format, ...)
    {
        StorageKeyName result;

        va_list args;
        va_start(args, format);
        vsnprintf(result.mKeyNameBuffer, sizeof(result.mKeyNameBuffer), format, args);
        va_end(args);

        return result;
    }

    // Explicit 0-filled key. MUST be initialized later
    static StorageKeyName Uninitialized()
    {
        StorageKeyName result;
        return result;
    }

private:
    // May only be created by the underlying constructor methods
    StorageKeyName() {}

    // Contains the storage for the key name because some strings may be formatted.
    char mKeyNameBuffer[PersistentStorageDelegate::kKeyLengthMax + 1] = { 0 };
};

/**
 * This is the common key allocation policy for all classes using
 * PersistentStorageDelegate storage.
 *
 * Keys should have the following formats:
 *
 * * Keys that are not tied to a specific fabric: "g/....".
 * * Keys that are tied to a specific fabric: "f/%x/...." where the %x gets
 *   replaced by the fabric index.
 */
class DefaultStorageKeyAllocator
{
private:
    DefaultStorageKeyAllocator() = default;

public:
    // Fabric Table
    static StorageKeyName FabricIndexInfo() { return StorageKeyName::FromConst("g/fidx"); }
    static StorageKeyName FabricNOC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/n", fabric); }
    static StorageKeyName FabricICAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/i", fabric); }
    static StorageKeyName FabricRCAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/r", fabric); }
    static StorageKeyName FabricMetadata(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/m", fabric); }
    static StorageKeyName FabricOpKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/o", fabric); }

    // Fail-safe handling
    static StorageKeyName FailSafeCommitMarkerKey() { return StorageKeyName::FromConst("g/fs/c"); }
    static StorageKeyName FailSafeNetworkConfig() { return StorageKeyName::FromConst("g/fs/n"); }

    // LastKnownGoodTime
    static StorageKeyName LastKnownGoodTimeKey() { return StorageKeyName::FromConst("g/lkgt"); }

    // Session resumption
    static StorageKeyName FabricSession(FabricIndex fabric, NodeId nodeId)
    {
        return StorageKeyName::Formatted("f/%x/s/%08" PRIX32 "%08" PRIX32, fabric, static_cast<uint32_t>(nodeId >> 32),
                                         static_cast<uint32_t>(nodeId));
    }

    static StorageKeyName SessionResumptionIndex() { return StorageKeyName::FromConst("g/sri"); }
    static StorageKeyName SessionResumption(const char * resumptionIdBase64)
    {
        return StorageKeyName::Formatted("g/s/%s", resumptionIdBase64);
    }

    // Access Control
    static StorageKeyName AccessControlAclEntry(FabricIndex fabric, size_t index)
    {
        return StorageKeyName::Formatted("f/%x/ac/0/%x", fabric, static_cast<unsigned>(index));
    }

    static StorageKeyName AccessControlExtensionEntry(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/ac/1", fabric); }

    // Group Message Counters
    static StorageKeyName GroupDataCounter() { return StorageKeyName::FromConst("g/gdc"); }
    static StorageKeyName GroupControlCounter() { return StorageKeyName::FromConst("g/gcc"); }

    // Device Information Provider
    static StorageKeyName UserLabelLengthKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/userlbl/%x", endpoint); }
    static StorageKeyName UserLabelIndexKey(EndpointId endpoint, uint32_t index)
    {
        return StorageKeyName::Formatted("g/userlbl/%x/%" PRIx32, endpoint, index);
    }

    // Group Data Provider

    // List of fabric indices that have endpoint-to-group associations defined.
    static StorageKeyName GroupFabricList() { return StorageKeyName::FromConst("g/gfl"); }
    static StorageKeyName FabricGroups(chip::FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/g", fabric); }
    static StorageKeyName FabricGroup(chip::FabricIndex fabric, chip::GroupId group)
    {
        return StorageKeyName::Formatted("f/%x/g/%x", fabric, group);
    }
    static StorageKeyName FabricGroupKey(chip::FabricIndex fabric, uint16_t index)
    {
        return StorageKeyName::Formatted("f/%x/gk/%x", fabric, index);
    }
    static StorageKeyName FabricGroupEndpoint(chip::FabricIndex fabric, chip::GroupId group, chip::EndpointId endpoint)
    {
        return StorageKeyName::Formatted("f/%x/g/%x/e/%x", fabric, group, endpoint);
    }
    static StorageKeyName FabricKeyset(chip::FabricIndex fabric, uint16_t keyset)
    {
        return StorageKeyName::Formatted("f/%x/k/%x", fabric, keyset);
    }

    static StorageKeyName AttributeValue(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId)
    {
        // Needs at most 26 chars: 6 for "g/a///", 4 for the endpoint id, 8 each
        // for the cluster and attribute ids.
        return StorageKeyName::Formatted("g/a/%x/%" PRIx32 "/%" PRIx32, endpointId, clusterId, attributeId);
    }

    // TODO: Should store fabric-specific parts of the binding list under keys
    // starting with "f/%x/".
    static StorageKeyName BindingTable() { return StorageKeyName::FromConst("g/bt"); }
    static StorageKeyName BindingTableEntry(uint8_t index) { return StorageKeyName::Formatted("g/bt/%x", index); }

    static StorageKeyName OTADefaultProviders() { return StorageKeyName::FromConst("g/o/dp"); }
    static StorageKeyName OTACurrentProvider() { return StorageKeyName::FromConst("g/o/cp"); }
    static StorageKeyName OTAUpdateToken() { return StorageKeyName::FromConst("g/o/ut"); }
    static StorageKeyName OTACurrentUpdateState() { return StorageKeyName::FromConst("g/o/us"); }
    static StorageKeyName OTATargetVersion() { return StorageKeyName::FromConst("g/o/tv"); }

    // Event number counter.
    static StorageKeyName IMEventNumber() { return StorageKeyName::FromConst("g/im/ec"); }
};

} // namespace chip
