/**
 *    Copyright (c) 2023 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.
 */

#import "MTRDemuxingStorage.h"

#import "MTRDeviceControllerFactory_Internal.h"
#import "MTRDeviceController_Internal.h"
#import "MTRLogging_Internal.h"

#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <platform/LockTracker.h>

using namespace chip;

static bool IsGlobalKey(NSString * key) { return [key hasPrefix:@"g/"]; }

/**
 * Checks for a key that is scoped to a specific fabric index.
 */
static bool IsIndexSpecificKey(NSString * key) { return [key hasPrefix:@"f/"]; }

/**
 * Extracts the fabric index from an index-specific key.  Fails if the key
 * is not index-specific or if a numeric FabricIndex could not be extracted
 * from it.
 */
static CHIP_ERROR ExtractIndexFromKey(NSString * key, FabricIndex * index)
{
    if (!IsIndexSpecificKey(key)) {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    auto * components = [key componentsSeparatedByString:@"/"];
    if (components.count < 3) {
        // Unexpected "f/something" without any actual data.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    auto * indexString = components[1];
    auto * scanner = [NSScanner scannerWithString:indexString];

    auto * charset = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"];
    charset = [charset invertedSet];

    if ([scanner scanCharactersFromSet:charset intoString:nil] == YES) {
        // Leading non-hex chars.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    unsigned int value;
    if ([scanner scanHexInt:&value] == NO) {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    if (scanner.atEnd == NO) {
        // Trailing garbage chars.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    if (!CanCastTo<FabricIndex>(value)) {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    *index = static_cast<FabricIndex>(value);
    return CHIP_NO_ERROR;
}

/**
 * Extracts the "index-specific" part of an index-specific key (i.e. the
 * part after "f/index/").
 */
static CHIP_ERROR ExtractIndexSpecificKey(NSString * key, NSString * __autoreleasing * extractedKey)
{
    if (!IsIndexSpecificKey(key)) {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    auto * components = [key componentsSeparatedByString:@"/"];
    if (components.count < 3) {
        // Unexpected "f/something" without any actual data.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    components = [components subarrayWithRange:NSMakeRange(2, components.count - 2)];
    *extractedKey = [components componentsJoinedByString:@"/"];
    return CHIP_NO_ERROR;
}

/**
 * Method to test whether a global key should be stored in memory only, as
 * opposed to being passed on to the actual storage related to controllers.
 */
static bool IsMemoryOnlyGlobalKey(NSString * key)
{
    if ([key isEqualToString:@"g/fidx"]) {
        // Fabric index list only needs to be stored in-memory, not persisted,
        // because we do not tie controllers to specific fabric indices.
        return true;
    }

    if ([key isEqualToString:@"g/fs/c"] || [key isEqualToString:@"g/fs/n"]) {
        // Just store the fail-safe markers in memory as well.  We could
        // plausibly not store them at all, since we never actually need to
        // clean up anything by fabric index, but this is safer in case
        // consumers try to read back right after writing.
        return true;
    }

    if ([key isEqualToString:@"g/lkgt"]) {
        // Store Last Known Good Time in memory only.  We never need this in
        // general, because we can always provide the wall-clock time.
        return true;
    }

    // We do not expect to see the "g/sri" or "g/s/*" keys for session
    // resumption, because we implement SessionResumptionStorage ourselves.

    // For now, put group global counters in memory.
    // TODO: we should inject a group counter manager that makes these counters
    // per-controller, not globally handled via storage.
    // See https://github.com/project-chip/connectedhomeip/issues/28510
    if ([key isEqualToString:@"g/gdc"] || [key isEqualToString:@"g/gcc"]) {
        return true;
    }

    // We do not expect to see "g/userlbl/*" User Label keys.

    // We do not expect to see the "g/gfl" key for endpoint-to-group
    // associations.

    // We do not expect to see the "g/a/*" keys for attribute values.

    // We do not expect to see the "g/sa/*" keys for attribute values.

    // We do not expect to see the "g/bt" and "g/bt/*" keys for the binding
    // table.

    // We do not expect to see the "g/o/*" OTA Requestor keys.

    // We do not expect to see the "g/im/ec" event number counter key.

    // We do not expect to see the "g/su/*" and "g/sum" keys for server-side
    // subscription resumption storage.

    // We do not expect to see the "g/scc/*" scenes keys.

    // We do not expect to see the "g/ts/tts", "g/ts/dntp", "g/ts/tz",
    // "g/ts/dsto" Time Synchronization keys.

    // We do not expect to see the "g/icd/cic" key; that's only used for an ICD
    // that sends check-in messages.

    // We do not expect to see the "g/icdfl" key; that's only used by
    // DefaultICDClientStorage, which Matter.framework does not use.

    // We do not expect to see the "g/tnd/*" Thread Network Directory keys.

    return false;
}

/**
 * Method to test whether an index-specific key should be stored in memory only, as
 * opposed to being passed on to the actual storage related to controllers.
 * The key string will have the "f/index/" bit already stripped off the
 * front of the key.
 */
static bool IsMemoryOnlyIndexSpecificKey(NSString * key)
{
    // Store all the fabric table bits in memory only.  This is done because the
    // fabric table expects none of these things to be stored in the case of a
    // "new fabric addition", which is what we always do when using
    // per-controller storage.
    //
    // TODO: Figure out which, if any, of these things we should also store for
    // later recall when starting a controller with storage we have used before.
    //
    // For future reference:
    //
    // n == NOC
    // i == ICAC
    // r == RCAC
    // m == Fabric metadata (TLV containing the vendor ID)
    // o == operational key, only written if internally generated.
    if ([key isEqualToString:@"n"] || [key isEqualToString:@"i"] || [key isEqualToString:@"r"] || [key isEqualToString:@"m"] ||
        [key isEqualToString:@"o"]) {
        return true;
    }

    // We do not expect to see the "s/*" keys for session resumption, because we
    // implement SessionResumptionStorage ourselves.

    // We do not expect to see the "ac/*" keys for ACL entries.

    // We do not expect to see the "g" or "g/*" keys for which endpoints are in which
    // group.

    // For now, just store group keysets and group keys in memory.
    // TODO: We want to start persisting these, per-controller, if we're going
    // to support group keys.  Or inject a GroupDataProvider of our own instead
    // of using Credentials::GroupDataProviderImp and then
    // not be tied to whatever storage format that uses.
    // https://github.com/project-chip/connectedhomeip/issues/28511
    if ([key hasPrefix:@"gk/"] || [key hasPrefix:@"k/"]) {
        return true;
    }

    // We do not expect to see the "icd/*" keys for the ICD Management table.

    // We do not expect to see the "e/*" scenes keys.

    // We do not epect to see the "icdc" or "icdk" keys, since those are only
    // used by DefaultICDClientStorage, which Matter.framework does not use.

    return false;
}

/**
 * Method to convert an index-specific key into a fully qualified key.
 */
static NSString * FullyQualifiedKey(FabricIndex index, NSString * key)
{
    return [NSString stringWithFormat:@"f/%x/%s", index, key.UTF8String];
}

MTRDemuxingStorage::MTRDemuxingStorage(MTRDeviceControllerFactory * factory)
    : mFactory(factory)
{
    mInMemoryStore = [[NSMutableDictionary alloc] init];
}

CHIP_ERROR MTRDemuxingStorage::SyncGetKeyValue(const char * key, void * buffer, uint16_t & size)
{
    assertChipStackLockedByCurrentThread();
    if (buffer == nullptr && size != 0) {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    NSString * keyString = [NSString stringWithUTF8String:key];

#if LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE
    MTR_LOG_DEBUG("MTRDemuxingStorage Sync Get Value for Key: %@", keyString);
#endif

    NSData * value;
    if (IsGlobalKey(keyString)) {
        value = GetGlobalValue(keyString);
    } else if (IsIndexSpecificKey(keyString)) {
        FabricIndex index;
        ReturnErrorOnFailure(ExtractIndexFromKey(keyString, &index));
        ReturnErrorOnFailure(ExtractIndexSpecificKey(keyString, &keyString));
        value = GetIndexSpecificValue(index, keyString);
    } else {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    if (value == nil) {
        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    }

    if (value.length > UINT16_MAX) {
        return CHIP_ERROR_PERSISTED_STORAGE_FAILED;
    }

    uint16_t valueSize = static_cast<uint16_t>(value.length);
    if (valueSize > size) {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    size = valueSize;

    if (size != 0) {
        // buffer is known to be non-null here.
        memcpy(buffer, value.bytes, size);
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR MTRDemuxingStorage::SyncSetKeyValue(const char * key, const void * value, uint16_t size)
{
    if (value == nullptr && size != 0) {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    NSString * keyString = [NSString stringWithUTF8String:key];
    NSData * valueData = (value == nullptr) ? [NSData data] : [NSData dataWithBytes:value length:size];

#if LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE
    MTR_LOG_DEBUG("MTRDemuxingStorage Set Key %@", keyString);
#endif

    if (IsGlobalKey(keyString)) {
        return SetGlobalValue(keyString, valueData);
    }

    if (IsIndexSpecificKey(keyString)) {
        FabricIndex index;
        ReturnErrorOnFailure(ExtractIndexFromKey(keyString, &index));
        ReturnErrorOnFailure(ExtractIndexSpecificKey(keyString, &keyString));
        return SetIndexSpecificValue(index, keyString, valueData);
    }

    return CHIP_ERROR_INVALID_ARGUMENT;
}

CHIP_ERROR MTRDemuxingStorage::SyncDeleteKeyValue(const char * key)
{
    NSString * keyString = [NSString stringWithUTF8String:key];

#if LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE
    MTR_LOG_DEBUG("MTRDemuxingStorage Delete Key: %@", keyString);
#endif

    if (IsGlobalKey(keyString)) {
        return DeleteGlobalValue(keyString);
    }

    if (IsIndexSpecificKey(keyString)) {
        FabricIndex index;
        ReturnErrorOnFailure(ExtractIndexFromKey(keyString, &index));
        ReturnErrorOnFailure(ExtractIndexSpecificKey(keyString, &keyString));
        return DeleteIndexSpecificValue(index, keyString);
    }

    return CHIP_ERROR_INVALID_ARGUMENT;
}

NSData * _Nullable MTRDemuxingStorage::GetGlobalValue(NSString * key)
{
    if (IsMemoryOnlyGlobalKey(key)) {
        return GetInMemoryValue(key);
    }

    MTR_LOG_ERROR("MTRDemuxingStorage reading unknown global key: %@", key);

    return nil;
}

NSData * _Nullable MTRDemuxingStorage::GetIndexSpecificValue(FabricIndex index, NSString * key)
{
    if (IsMemoryOnlyIndexSpecificKey(key)) {
        return GetInMemoryValue(FullyQualifiedKey(index, key));
    }

    return nil;
}

CHIP_ERROR MTRDemuxingStorage::SetGlobalValue(NSString * key, NSData * data)
{
    if (IsMemoryOnlyGlobalKey(key)) {
        // Fabric index list only needs to be stored in-memory, not persisted,
        // because we do not tie controllers to specific fabric indices.
        return SetInMemoryValue(key, data);
    }

    MTR_LOG_ERROR("MTRDemuxingStorage setting unknown global key: %@", key);

    return CHIP_ERROR_PERSISTED_STORAGE_FAILED;
}

CHIP_ERROR MTRDemuxingStorage::SetIndexSpecificValue(FabricIndex index, NSString * key, NSData * data)
{
    if ([key isEqualToString:@"n"]) {
        // Index-scoped "n" is NOC.
        auto * controller = [mFactory runningControllerForFabricIndex:index];
        if (controller == nil) {
            return CHIP_ERROR_PERSISTED_STORAGE_FAILED;
        }

        ReturnErrorOnFailure([controller.controllerDataStore storeLastLocallyUsedNOC:data]);
    }

    if (IsMemoryOnlyIndexSpecificKey(key)) {
        return SetInMemoryValue(FullyQualifiedKey(index, key), data);
    }

    return CHIP_ERROR_PERSISTED_STORAGE_FAILED;
}

CHIP_ERROR MTRDemuxingStorage::DeleteGlobalValue(NSString * key)
{
    if (IsMemoryOnlyGlobalKey(key)) {
        return DeleteInMemoryValue(key);
    }

    MTR_LOG_ERROR("MTRDemuxingStorage deleting unknown global key: %@", key);

    return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}

CHIP_ERROR MTRDemuxingStorage::DeleteIndexSpecificValue(FabricIndex index, NSString * key)
{
    if (IsMemoryOnlyIndexSpecificKey(key)) {
        return DeleteInMemoryValue(FullyQualifiedKey(index, key));
    }

    return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}

NSData * _Nullable MTRDemuxingStorage::GetInMemoryValue(NSString * key) { return mInMemoryStore[key]; }

CHIP_ERROR MTRDemuxingStorage::SetInMemoryValue(NSString * key, NSData * data)
{
    mInMemoryStore[key] = data;
    return CHIP_NO_ERROR;
}

CHIP_ERROR MTRDemuxingStorage::DeleteInMemoryValue(NSString * key)
{
    BOOL present = (mInMemoryStore[key] != nil);
    if (present) {
        [mInMemoryStore removeObjectForKey:key];
    }
    return present ? CHIP_NO_ERROR : CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}
