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

#pragma once

#include <lib/support/Span.h>

#include "commands/common/CHIPCommand.h"
#include "commands/common/Command.h"
#include "commands/common/Commands.h"

class ShowControllerGroups : public CHIPCommand
{
public:
    ShowControllerGroups(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("show-groups", credsIssuerConfig) {}
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    bool FindKeySetId(chip::FabricIndex fabricIndex, chip::GroupId groupId, chip::KeysetId & keysetId)
    {
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        auto iter                                                = groupDataProvider->IterateGroupKeys(fabricIndex);
        chip::Credentials::GroupDataProvider::GroupKey groupKey;
        while (iter->Next(groupKey))
        {
            if (groupKey.group_id == groupId)
            {
                keysetId = groupKey.keyset_id;
                iter->Release();
                return true;
            }
        }
        iter->Release();
        return false;
    }

    CHIP_ERROR RunCommand() override
    {
        fprintf(stderr, "\n");
        fprintf(stderr, "  +-------------------------------------------------------------------------------------+\n");
        fprintf(stderr, "  | Available Groups :                                                                  |\n");
        fprintf(stderr, "  +-------------------------------------------------------------------------------------+\n");
        fprintf(stderr, "  | Group Id   |  KeySet Id     |   Group Name                                          |\n");
        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        auto it                                                  = groupDataProvider->IterateGroupInfo(fabricIndex);
        chip::Credentials::GroupDataProvider::GroupInfo group;
        if (it)
        {
            while (it->Next(group))
            {
                chip::KeysetId keysetId;
                if (FindKeySetId(fabricIndex, group.group_id, keysetId))
                {
                    fprintf(stderr, "  | 0x%-12x  0x%-13x  %-50s |\n", group.group_id, keysetId, group.name);
                }
                else
                {
                    fprintf(stderr, "  | 0x%-12x  %-15s  %-50s |\n", group.group_id, "None", group.name);
                }
            }
            it->Release();
        }
        fprintf(stderr, "  +-------------------------------------------------------------------------------------+\n");
        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }
};

class AddGroup : public CHIPCommand
{
public:
    AddGroup(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("add-group", credsIssuerConfig)
    {
        AddArgument("groupName", &groupName);
        AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId);
    }
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(20); }

    CHIP_ERROR RunCommand() override
    {
        if (strlen(groupName) > CHIP_CONFIG_MAX_GROUP_NAME_LENGTH || groupId == chip::kUndefinedGroupId)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        chip::Credentials::GroupDataProvider::GroupInfo group;

        group.SetName(groupName);
        group.group_id = groupId;
        ReturnErrorOnFailure(groupDataProvider->SetGroupInfo(fabricIndex, group));

        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }

private:
    char * groupName;
    chip::GroupId groupId;
};

class RemoveGroup : public CHIPCommand
{
public:
    RemoveGroup(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("remove-group", credsIssuerConfig)
    {
        AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId);
    }
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    CHIP_ERROR RunCommand() override
    {
        if (groupId == chip::kUndefinedGroupId)
        {
            ChipLogError(chipTool, "Invalid group Id : 0x%x", groupId);
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        ReturnErrorOnFailure(groupDataProvider->RemoveGroupInfo(fabricIndex, groupId));
        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }

private:
    chip::GroupId groupId;
};

class ShowKeySets : public CHIPCommand
{
public:
    ShowKeySets(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("show-keysets", credsIssuerConfig) {}
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    CHIP_ERROR RunCommand() override
    {
        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        chip::Credentials::GroupDataProvider::KeySet keySet;

        fprintf(stderr, "\n");
        fprintf(stderr, "  +-------------------------------------------------------------------------------------+\n");
        fprintf(stderr, "  | Available KeySets :                                                                 |\n");
        fprintf(stderr, "  +-------------------------------------------------------------------------------------+\n");
        fprintf(stderr, "  | KeySet Id   |   Key Policy                                                          |\n");

        auto it = groupDataProvider->IterateKeySets(fabricIndex);
        if (it)
        {
            while (it->Next(keySet))
            {
                fprintf(stderr, "  | 0x%-12x  %-66s  |\n", keySet.keyset_id,
                        (keySet.policy == chip::Credentials::GroupDataProvider::SecurityPolicy::kCacheAndSync) ? "Cache and Sync"
                                                                                                               : "Trust First");
            }
            it->Release();
        }
        fprintf(stderr, "  +-------------------------------------------------------------------------------------+\n");
        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }
};

class BindKeySet : public CHIPCommand
{
public:
    BindKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("bind-keyset", credsIssuerConfig)
    {
        AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId);
        AddArgument("keysetId", 0, UINT16_MAX, &keysetId);
    }
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    CHIP_ERROR RunCommand() override
    {
        size_t current_count                                     = 0;
        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();

        auto iter     = groupDataProvider->IterateGroupKeys(fabricIndex);
        current_count = iter->Count();
        iter->Release();

        ReturnErrorOnFailure(groupDataProvider->SetGroupKeyAt(fabricIndex, current_count,
                                                              chip::Credentials::GroupDataProvider::GroupKey(groupId, keysetId)));

        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }

private:
    chip::GroupId groupId;
    chip::KeysetId keysetId;
};

class UnbindKeySet : public CHIPCommand
{
public:
    UnbindKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("unbind-keyset", credsIssuerConfig)
    {
        AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId);
        AddArgument("keysetId", 0, UINT16_MAX, &keysetId);
    }
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    CHIP_ERROR RunCommand() override
    {
        size_t index                                             = 0;
        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        auto iter                                                = groupDataProvider->IterateGroupKeys(fabricIndex);
        size_t maxCount                                          = iter->Count();
        chip::Credentials::GroupDataProvider::GroupKey groupKey;
        while (iter->Next(groupKey))
        {
            if (groupKey.group_id == groupId && groupKey.keyset_id == keysetId)
            {
                break;
            }
            index++;
        }
        iter->Release();
        if (index >= maxCount)
        {
            return CHIP_ERROR_INTERNAL;
        }

        ReturnErrorOnFailure(groupDataProvider->RemoveGroupKeyAt(fabricIndex, index));

        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }

private:
    chip::GroupId groupId;
    chip::KeysetId keysetId;
};

class AddKeySet : public CHIPCommand
{
public:
    AddKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("add-keysets", credsIssuerConfig)
    {
        AddArgument("keysetId", 0, UINT16_MAX, &keysetId);
        AddArgument("keyPolicy", 0, UINT16_MAX, &keyPolicy);
        AddArgument("validityTime", 0, UINT64_MAX, &validityTime);
        AddArgument("EpochKey", &epochKey);
    }
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    CHIP_ERROR RunCommand() override
    {
        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();
        uint8_t compressed_fabric_id[sizeof(uint64_t)];
        chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
        ReturnLogErrorOnFailure(CurrentCommissioner().GetCompressedFabricIdBytes(compressed_fabric_id_span));

        if ((keyPolicy != chip::Credentials::GroupDataProvider::SecurityPolicy::kCacheAndSync &&
             keyPolicy != chip::Credentials::GroupDataProvider::SecurityPolicy::kTrustFirst) ||
            (epochKey.size()) != chip::Credentials::GroupDataProvider::EpochKey::kLengthBytes)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        chip::Credentials::GroupDataProvider::KeySet keySet(keysetId, keyPolicy, 1);
        chip::Credentials::GroupDataProvider::EpochKey epoch_key;
        epoch_key.start_time = validityTime;
        memcpy(epoch_key.key, epochKey.data(), chip::Credentials::GroupDataProvider::EpochKey::kLengthBytes);

        memcpy(keySet.epoch_keys, &epoch_key, sizeof(chip::Credentials::GroupDataProvider::EpochKey));
        ReturnErrorOnFailure(groupDataProvider->SetKeySet(fabricIndex, compressed_fabric_id_span, keySet));

        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }

private:
    chip::KeysetId keysetId;
    chip::Credentials::GroupDataProvider::SecurityPolicy keyPolicy;
    uint64_t validityTime;
    chip::ByteSpan epochKey;
};

class RemoveKeySet : public CHIPCommand
{
public:
    RemoveKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("remove-keyset", credsIssuerConfig)
    {
        AddArgument("keysetId", 0, UINT16_MAX, &keysetId);
    }
    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); }

    CHIP_ERROR RunCommand() override
    {
        CHIP_ERROR err                                           = CHIP_NO_ERROR;
        chip::FabricIndex fabricIndex                            = CurrentCommissioner().GetFabricIndex();
        chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider();

        // Unbind all group
        size_t index = 0;
        auto iter    = groupDataProvider->IterateGroupKeys(fabricIndex);
        chip::Credentials::GroupDataProvider::GroupKey groupKey;
        while (iter->Next(groupKey))
        {
            if (groupKey.keyset_id == keysetId)
            {
                err = groupDataProvider->RemoveGroupKeyAt(fabricIndex, index);
                if (err != CHIP_NO_ERROR)
                {
                    break;
                }
            }
            index++;
        }
        iter->Release();

        if (err == CHIP_NO_ERROR)
        {
            return err;
        }
        ReturnErrorOnFailure(groupDataProvider->RemoveKeySet(fabricIndex, keysetId));

        SetCommandExitStatus(CHIP_NO_ERROR);
        return CHIP_NO_ERROR;
    }

private:
    chip::KeysetId keysetId;
};

void registerCommandsGroup(Commands & commands, CredentialIssuerCommands * credsIssuerConfig)
{
    const char * clusterName = "GroupSettings";

    commands_list clusterCommands = {
        make_unique<ShowControllerGroups>(credsIssuerConfig),
        make_unique<AddGroup>(credsIssuerConfig),
        make_unique<RemoveGroup>(credsIssuerConfig),
        make_unique<ShowKeySets>(credsIssuerConfig),
        make_unique<BindKeySet>(credsIssuerConfig),
        make_unique<UnbindKeySet>(credsIssuerConfig),
        make_unique<AddKeySet>(credsIssuerConfig),
        make_unique<RemoveKeySet>(credsIssuerConfig),
    };

    commands.Register(clusterName, clusterCommands);
}
