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

#include <optional>
#include <stdint.h>
#include <sys/types.h>

#include <app/util/basic-types.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPError.h>
#include <lib/core/ClusterEnums.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CommonIterator.h>

namespace chip {
namespace Credentials {

class GroupDataProvider
{
public:
    using SecurityPolicy                                  = app::Clusters::GroupKeyManagement::GroupKeySecurityPolicyEnum;
    static constexpr KeysetId kIdentityProtectionKeySetId = 0;
    static constexpr size_t kMaxListeners                 = 2;

    struct GroupInfo
    {
        static constexpr size_t kGroupNameMax = CHIP_CONFIG_MAX_GROUP_NAME_LENGTH;
        enum class Flags : uint8_t
        {
            kHasAuxiliaryACL = 0b00000001,
            kMcastAddrPolicy = 0b00000010,
        };
        static constexpr uint8_t kFlagsDefault = to_underlying(GroupInfo::Flags::kMcastAddrPolicy);

        // Identifies group within the scope of the given Fabric
        GroupId group_id = kUndefinedGroupId;
        // Lastest group name written for a given GroupId on any Endpoint via the Groups cluster
        char name[kGroupNameMax + 1] = { 0 };
        uint8_t flags                = kFlagsDefault;
        uint16_t count               = 0;

        GroupInfo() { SetName(nullptr); }
        GroupInfo(const GroupInfo & other) { Copy(other); }
        GroupInfo(const char * groupName) { SetName(groupName); }
        GroupInfo(const CharSpan & groupName) { SetName(groupName); }
        GroupInfo(GroupId id, const char * groupName, uint8_t groupFlags = kFlagsDefault) : group_id(id), flags(groupFlags)
        {
            SetName(groupName);
        }
        GroupInfo(GroupId id, const CharSpan & groupName, uint8_t groupFlags = kFlagsDefault) : group_id(id), flags(groupFlags)
        {
            SetName(groupName);
        }
        void SetName(const char * groupName)
        {
            if (nullptr == groupName)
            {
                name[0] = 0;
            }
            else
            {
                Platform::CopyString(name, groupName);
            }
        }
        void SetName(const CharSpan & groupName)
        {
            if (nullptr == groupName.data())
            {
                name[0] = 0;
            }
            else
            {
                Platform::CopyString(name, groupName);
            }
        }
        void Copy(const GroupInfo & other)
        {
            if (this != &other)
            {
                group_id = other.group_id;
                flags    = other.flags;
                SetName(other.name);
            }
        }
        bool HasAuxiliaryACL() const { return (flags & static_cast<uint8_t>(Flags::kHasAuxiliaryACL)); }
        bool UsePerGroupAddress() const { return (flags & static_cast<uint8_t>(Flags::kMcastAddrPolicy)); }

        bool operator==(const GroupInfo & other) const
        {
            return (this->group_id == other.group_id) && !strncmp(this->name, other.name, kGroupNameMax);
        }
        GroupInfo & operator=(const GroupInfo & other)
        {
            Copy(other);
            return *this;
        }
    };

    struct GroupKey
    {
        GroupKey() = default;
        GroupKey(GroupId group, KeysetId keyset) : group_id(group), keyset_id(keyset) {}
        // Identifies group within the scope of the given Fabric
        GroupId group_id = kUndefinedGroupId;
        // Set of group keys that generate operational group keys for use with this group
        KeysetId keyset_id = 0;
        bool operator==(const GroupKey & other) const
        {
            return this->group_id == other.group_id && this->keyset_id == other.keyset_id;
        }
    };

    struct GroupEndpoint
    {
        GroupEndpoint() = default;
        GroupEndpoint(GroupId group, EndpointId endpoint) : group_id(group), endpoint_id(endpoint) {}
        // Identifies group within the scope of the given Fabric
        GroupId group_id = kUndefinedGroupId;
        // Endpoint on the Node to which messages to this group may be forwarded
        EndpointId endpoint_id = kInvalidEndpointId;

        bool operator==(const GroupEndpoint & other) const
        {
            return this->group_id == other.group_id && this->endpoint_id == other.endpoint_id;
        }
    };

    struct GroupSession
    {
        GroupSession()   = default;
        GroupId group_id = kUndefinedGroupId;
        FabricIndex fabric_index;
        SecurityPolicy security_policy;
        Crypto::SymmetricKeyContext * keyContext = nullptr;
    };

    // An EpochKey is a single key usable to determine an operational group key
    struct EpochKey
    {
        static constexpr size_t kLengthBytes = Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES;
        // Validity start time in microseconds since 2000-01-01T00:00:00 UTC ("the Epoch")
        uint64_t start_time;
        // Actual key bits. Depending on context, it may be a raw epoch key (as seen within `SetKeySet` calls)
        // or it may be the derived operational group key (as seen in any other usage).
        uint8_t key[kLengthBytes];

        void Clear()
        {
            start_time = 0;
            Crypto::ClearSecretData(&key[0], sizeof(key));
        }
    };

    // A operational group key set, usable by many GroupState mappings
    struct KeySet
    {
        static constexpr size_t kEpochKeysMax = 3;

        KeySet() { ClearKeys(); }
        KeySet(uint16_t id, SecurityPolicy policy_id, uint8_t num_keys) : keyset_id(id), policy(policy_id), num_keys_used(num_keys)
        {
            ClearKeys();
        }

        // The actual keys for the group key set
        EpochKey epoch_keys[kEpochKeysMax];
        // Logical id provided by the Administrator that configured the entry
        uint16_t keyset_id = 0;
        // Security policy to use for groups that use this keyset
        SecurityPolicy policy = SecurityPolicy::kTrustFirst;
        // Number of keys present
        uint8_t num_keys_used = 0;

        bool operator==(const KeySet & other) const
        {
            VerifyOrReturnError(this->policy == other.policy && this->num_keys_used == other.num_keys_used, false);
            return !memcmp(this->epoch_keys, other.epoch_keys, this->num_keys_used * sizeof(EpochKey));
        }

        void ClearKeys()
        {
            for (size_t key_idx = 0; key_idx < kEpochKeysMax; ++key_idx)
            {
                epoch_keys[key_idx].Clear();
            }
        }
    };

    /**
     *  Interface to listen for changes in the Group info.
     */
    class GroupListener
    {
    public:
        virtual ~GroupListener() = default;
        /**
         *  Callback invoked when a new group is added.
         *
         *  @param[in] new_group  GroupInfo structure of the new group.
         */
        virtual void OnGroupAdded(FabricIndex fabric_index, const GroupInfo & new_group) = 0;
        /**
         *  Callback invoked when an existing group is removed.
         *
         *  @param[in] old_group  GroupInfo structure of the removed group.
         */
        virtual void OnGroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group) = 0;
        /**
         *  Callback invoked when an existing group is modified.
         *  The modifications may be any of the following:
         *  - Endpoints List modified
         *  - KeySetID modified
         *  - Flags modified (kHasAuxiliaryACL or kMcastAddrPolicy)
         *
         * Note that this callback is not invoked when the group is added or removed.
         * Those events are handled by the OnGroupAdded and OnGroupRemoved callbacks respectively.
         *
         *  @param[in] modified_group_id  ID of the modified group.
         */
        virtual void OnGroupModified(FabricIndex fabric_index, const GroupId & modified_group_id){};
    };

    using GroupInfoIterator    = CommonIterator<GroupInfo>;
    using GroupKeyIterator     = CommonIterator<GroupKey>;
    using EndpointIterator     = CommonIterator<GroupEndpoint>;
    using KeySetIterator       = CommonIterator<KeySet>;
    using GroupSessionIterator = CommonIterator<GroupSession>;

    GroupDataProvider(uint16_t maxGroupsPerFabric, uint16_t maxGroupKeysPerFabric) :
        mMaxGroupsPerFabric(maxGroupsPerFabric), mMaxGroupKeysPerFabric(maxGroupKeysPerFabric)
    {}

    enum class GroupCleanupPolicy
    {
        kDeleteGroupIfEmpty, // Default behavior for legacy Groups
        kKeepGroupIfEmpty    // Required for Groupcast Sender feature
    };

    virtual ~GroupDataProvider() = default;

    // Not copyable
    GroupDataProvider(const GroupDataProvider &)             = delete;
    GroupDataProvider & operator=(const GroupDataProvider &) = delete;

    // TODO(#72056): Once groupcast is enabled by default, this should just return mMaxGroupsPerFabric. See GroupDataProviderImpl()
    // constructor.
    uint16_t GetMaxGroupsPerFabric() const
    {
        return static_cast<uint16_t>(IsGroupcastEnabled() ? (getMaxMembershipCount() / 2) : mMaxGroupsPerFabric);
    }
    uint16_t GetMaxGroupKeysPerFabric() const { return mMaxGroupKeysPerFabric; }

    /**
     *  Initialize the GroupDataProvider, including possibly any persistent
     *  data store initialization done by the implementation. Must be called once
     *  before any other API succeeds.
     *
     *  @retval #CHIP_ERROR_INCORRECT_STATE if called when already initialized.
     *  @retval #CHIP_NO_ERROR on success
     */
    virtual CHIP_ERROR Init() = 0;
    virtual void Finish()     = 0;

    //
    // Group Table
    //

    // By id
    virtual CHIP_ERROR SetGroupInfo(FabricIndex fabric_index, const GroupInfo & info)             = 0;
    virtual CHIP_ERROR GetGroupInfo(FabricIndex fabric_index, GroupId group_id, GroupInfo & info) = 0;
    virtual CHIP_ERROR RemoveGroupInfo(FabricIndex fabric_index, GroupId group_id)                = 0;
    // By index
    virtual CHIP_ERROR SetGroupInfoAt(FabricIndex fabric_index, size_t index, const GroupInfo & info) = 0;
    virtual CHIP_ERROR GetGroupInfoAt(FabricIndex fabric_index, size_t index, GroupInfo & info)       = 0;
    virtual CHIP_ERROR RemoveGroupInfoAt(FabricIndex fabric_index, size_t index)                      = 0;
    // Endpoints
    virtual bool HasEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id)          = 0;
    virtual CHIP_ERROR AddEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id)    = 0;
    virtual CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id,
                                      GroupCleanupPolicy cleanupPolicy)                                   = 0;
    virtual CHIP_ERROR RemoveEndpointAllGroups(FabricIndex fabric_index, EndpointId endpoint_id,
                                               GroupCleanupPolicy cleanupPolicy)                          = 0;
    virtual CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id) = 0;
    virtual CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, EndpointId endpoint_id)                   = 0;
    virtual CHIP_ERROR RemoveEndpoints(FabricIndex fabric_index, GroupId group_id)                        = 0;
    // Iterators
    /**
     *  Creates an iterator that may be used to obtain the list of groups associated with the given fabric.
     *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     *  Modifying the group table during the iteration is currently not supported, and may yield unexpected behaviour.
     *  @retval An instance of EndpointIterator on success
     *  @retval nullptr if no iterator instances are available.
     */
    virtual GroupInfoIterator * IterateGroupInfo(FabricIndex fabric_index) = 0;
    /**
     *  Creates an iterator that may be used to obtain the list of (group, endpoint) pairs associated with the given fabric.
     *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     *  Modifying the group table during the iteration is currently not supported, and may yield unexpected behaviour.
     *  If you wish to iterate only the endpoints of a particular group id you can provide the optional `group_id` to do so.
     *  @retval An instance of EndpointIterator on success
     *  @retval nullptr if no iterator instances are available.
     */
    virtual EndpointIterator * IterateEndpoints(FabricIndex fabric_index, std::optional<GroupId> group_id = std::nullopt) = 0;

    //
    // Group-Key map
    //

    virtual CHIP_ERROR SetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId keyset_id)   = 0;
    virtual CHIP_ERROR SetGroupKeyAt(FabricIndex fabric_index, size_t index, const GroupKey & info)  = 0;
    virtual CHIP_ERROR GetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId & keyset_id) = 0;
    virtual CHIP_ERROR GetGroupKeyAt(FabricIndex fabric_index, size_t index, GroupKey & info)        = 0;
    virtual CHIP_ERROR RemoveGroupKeyAt(FabricIndex fabric_index, size_t index)                      = 0;
    virtual CHIP_ERROR RemoveGroupKeys(FabricIndex fabric_index)                                     = 0;

    /**
     *  Creates an iterator that may be used to obtain the list of (group, keyset) pairs associated with the given fabric.
     *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     *  Modifying the keyset mappings during the iteration is currently not supported, and may yield unexpected behaviour.
     *  @retval An instance of GroupKeyIterator on success
     *  @retval nullptr if no iterator instances are available.
     */
    virtual GroupKeyIterator * IterateGroupKeys(FabricIndex fabric_index) = 0;

    //
    // Key Sets
    //

    virtual CHIP_ERROR SetKeySet(FabricIndex fabric_index, const ByteSpan & compressed_fabric_id, const KeySet & keys) = 0;
    virtual CHIP_ERROR GetKeySet(FabricIndex fabric_index, KeysetId keyset_id, KeySet & keys)                          = 0;
    virtual CHIP_ERROR RemoveKeySet(FabricIndex fabric_index, KeysetId keyset_id)                                      = 0;

    /**
     * @brief Obtain the actual operational Identity Protection Key (IPK) keyset for a given
     *        fabric. These keys are used by the CASE protocol, and do not participate in
     *        any direct traffic encryption. Since the identity protection operational keyset
     *        is used in multiple key derivations and procedures, it cannot be hidden behind a
     *        SymmetricKeyContext, and must be obtainable by value.
     *
     * @param fabric_index - Fabric index for which to get the IPK operational keyset
     * @param out_keyset - Reference to a KeySet where the IPK keys will be stored on success
     * @return CHIP_NO_ERROR on success, CHIP_ERROR_NOT_FOUND if the IPK keyset is somehow unavailable
     *         or another CHIP_ERROR value if an internal storage error occurs.
     */
    virtual CHIP_ERROR GetIpkKeySet(FabricIndex fabric_index, KeySet & out_keyset) = 0;

    /**
     *  Creates an iterator that may be used to obtain the list of key sets associated with the given fabric.
     *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     *  Modifying the key sets table during the iteration is currently not supported, and may yield unexpected behaviour.
     *
     *  @retval An instance of KeySetIterator on success
     *  @retval nullptr if no iterator instances are available.
     */
    virtual KeySetIterator * IterateKeySets(FabricIndex fabric_index) = 0;

    // Fabrics
    virtual CHIP_ERROR RemoveFabric(FabricIndex fabric_index) = 0;

    // Decryption
    virtual GroupSessionIterator * IterateGroupSessions(uint16_t session_id)                        = 0;
    virtual Crypto::SymmetricKeyContext * GetKeyContext(FabricIndex fabric_index, GroupId group_id) = 0;

    // Listener
    void SetListener(GroupListener * listener)
    {
        for (size_t i = 0; listener && (i < kMaxListeners); ++i)
        {
            if (nullptr == mListeners[i])
            {
                mListeners[i] = listener;
                return;
            }
        }
    }
    void RemoveListener(GroupListener * listener)
    {
        for (size_t i = 0; listener && (i < kMaxListeners); ++i)
        {
            if (listener == mListeners[i])
            {
                mListeners[i] = nullptr;
                return;
            }
        }
    }

    void SetGroupcastEnabled(bool groupcastVal) { mGroupcastEnabled = groupcastVal; }

    bool IsGroupcastEnabled() const { return mGroupcastEnabled; }

    // Groupcast
    virtual uint16_t getMaxMembershipCount() const = 0;
    virtual uint16_t getMaxMcastAddrCount() const  = 0;

    /**
     * @brief Check if a notification is needed for Auxiliary ACL changes and reset the flag.
     *
     * This method returns true if the last set of operations (e.g., SetGroupInfo, RemoveGroupInfo)
     * somehow changed the Auxiliary ACL status of a group. Calling this method resets the internal flag.
     *
     * @return true if a notification is needed, false otherwise.
     */
    virtual bool ConsumeAuxAclNotificationNeeded() = 0;

protected:
    void GroupAdded(FabricIndex fabric_index, const GroupInfo & new_group)
    {
        for (auto * listener : mListeners)
        {
            if (listener != nullptr)
            {
                listener->OnGroupAdded(fabric_index, new_group);
            }
        }
    }
    void GroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group)
    {
        for (auto * listener : mListeners)
        {
            if (listener != nullptr)
            {
                listener->OnGroupRemoved(fabric_index, old_group);
            }
        }
    }
    void GroupModified(FabricIndex fabric_index, const GroupId & modified_group_id)
    {
        for (auto * listener : mListeners)
        {
            if (listener != nullptr)
            {
                listener->OnGroupModified(fabric_index, modified_group_id);
            }
        }
    }
    const uint16_t mMaxGroupsPerFabric;
    const uint16_t mMaxGroupKeysPerFabric;
    GroupListener * mListeners[kMaxListeners] = { nullptr };
    bool mGroupcastEnabled                    = false;
};

/**
 * @brief Utility Set the IPK Epoch key on a GroupDataProvider assuming a single IPK
 *
 * This utility replaces having to call `GroupDataProvider::SetKeySet` for the simple situation of a
 * single IPK for a fabric, if a single epoch key is used. Start time will be set to 0 ("was always valid")
 *
 * @param provider - pointer to GroupDataProvider on which to set the IPK
 * @param fabric_index - fabric index within the GroupDataProvider for which to set the IPK
 * @param ipk_epoch_span - Span containing the IPK epoch key
 * @param compressed_fabric_id - Compressed fabric ID associated with the fabric, for key derivation
 * @return CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT on any bad argument, other CHIP_ERROR values
 *         from implementation on other errors
 */
inline CHIP_ERROR SetSingleIpkEpochKey(GroupDataProvider * provider, FabricIndex fabric_index, const ByteSpan & ipk_epoch_span,
                                       const ByteSpan & compressed_fabric_id)
{
    GroupDataProvider::KeySet ipkKeySet(GroupDataProvider::kIdentityProtectionKeySetId,
                                        GroupDataProvider::SecurityPolicy::kTrustFirst, 1);

    VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(ipk_epoch_span.size() == sizeof(ipkKeySet.epoch_keys[0].key), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(compressed_fabric_id.size() == sizeof(uint64_t), CHIP_ERROR_INVALID_ARGUMENT);

    ipkKeySet.epoch_keys[0].start_time = 0;
    memcpy(&ipkKeySet.epoch_keys[0].key, ipk_epoch_span.data(), ipk_epoch_span.size());

    // Set a single IPK, validate key derivation follows spec
    return provider->SetKeySet(fabric_index, compressed_fabric_id, ipkKeySet);
}

/**
 * Instance getter for the global GroupDataProvider.
 *
 * Callers have to externally synchronize usage of this function.
 *
 * @return The global Group Data Provider
 */
GroupDataProvider * GetGroupDataProvider();

/**
 * Instance setter for the global GroupDataProvider.
 *
 * Callers have to externally synchronize usage of this function.
 *
 * The `provider` can be set to nullptr if the owner is done with it fully.
 *
 * @param[in] provider pointer to the Group Data Provider global isntance to use
 */
void SetGroupDataProvider(GroupDataProvider * provider);

} // namespace Credentials
} // namespace chip
