/*
 *
 *    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 <lib/core/StringBuilderAdapters.h>
#include <pw_unit_test/framework.h>

#include <app/util/binding-table.h>
#include <app/util/config.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/TestPersistentStorageDelegate.h>
#include <lib/support/UnitTestRegistration.h>

using chip::BindingTable;

namespace {

void VerifyTableSame(BindingTable & table, const std::vector<EmberBindingTableEntry> & expected)
{
    ASSERT_EQ(table.Size(), expected.size());
    auto iter1 = table.begin();
    auto iter2 = expected.begin();
    while (iter2 != expected.end())
    {
        EXPECT_EQ(*iter1, *iter2);
        ++iter1;
        ++iter2;
    }
    EXPECT_EQ(iter1, table.end());
}

void VerifyRestored(chip::TestPersistentStorageDelegate & storage, const std::vector<EmberBindingTableEntry> & expected)
{
    BindingTable restoredTable;
    restoredTable.SetPersistentStorage(&storage);
    EXPECT_EQ(restoredTable.LoadFromStorage(), CHIP_NO_ERROR);
    VerifyTableSame(restoredTable, expected);
}

TEST(TestBindingTable, TestEmptyBindingTable)
{
    BindingTable table;
    chip::TestPersistentStorageDelegate testStorage;
    table.SetPersistentStorage(&testStorage);
    EXPECT_EQ(table.Size(), 0u);
    EXPECT_EQ(table.begin(), table.end());
}

TEST(TestBindingTable, TestAdd)
{
    BindingTable table;
    chip::TestPersistentStorageDelegate testStorage;
    table.SetPersistentStorage(&testStorage);
    EmberBindingTableEntry unusedEntry;
    unusedEntry.type = MATTER_UNUSED_BINDING;
    EXPECT_EQ(table.Add(unusedEntry), CHIP_ERROR_INVALID_ARGUMENT);
    for (uint8_t i = 0; i < MATTER_BINDING_TABLE_SIZE; i++)
    {
        EXPECT_EQ(table.Add(EmberBindingTableEntry::ForNode(0, i, 0, 0, std::nullopt)), CHIP_NO_ERROR);
    }
    EXPECT_EQ(table.Add(EmberBindingTableEntry::ForNode(0, 0, 0, 0, std::nullopt)), CHIP_ERROR_NO_MEMORY);
    EXPECT_EQ(table.Size(), MATTER_BINDING_TABLE_SIZE);

    auto iter = table.begin();
    for (uint8_t i = 0; i < MATTER_BINDING_TABLE_SIZE; i++)
    {
        EXPECT_NE(iter, table.end());
        EXPECT_EQ(iter->nodeId, i);
        EXPECT_EQ(iter.GetIndex(), i);
        ++iter;
    }
    EXPECT_EQ(iter, table.end());
}

TEST(TestBindingTable, TestRemoveThenAdd)
{
    BindingTable table;
    chip::TestPersistentStorageDelegate testStorage;
    table.SetPersistentStorage(&testStorage);
    EXPECT_EQ(table.Add(EmberBindingTableEntry::ForNode(0, 0, 0, 0, std::nullopt)), CHIP_NO_ERROR);
    auto iter = table.begin();
    EXPECT_EQ(table.RemoveAt(iter), CHIP_NO_ERROR);
    EXPECT_EQ(iter, table.end());
    EXPECT_EQ(table.Size(), 0u);
    EXPECT_EQ(table.begin(), table.end());
    for (uint8_t i = 0; i < MATTER_BINDING_TABLE_SIZE; i++)
    {
        EXPECT_EQ(table.Add(EmberBindingTableEntry::ForNode(0, i, 0, 0, std::nullopt)), CHIP_NO_ERROR);
    }
    iter = table.begin();
    ++iter;
    EXPECT_EQ(table.RemoveAt(iter), CHIP_NO_ERROR);
    EXPECT_EQ(table.Size(), MATTER_BINDING_TABLE_SIZE - 1);
    EXPECT_EQ(iter->nodeId, 2u);
    EXPECT_EQ(iter.GetIndex(), 2u);
    auto iterCheck = table.begin();
    ++iterCheck;
    EXPECT_EQ(iter, iterCheck);

    EXPECT_EQ(table.Add(EmberBindingTableEntry::ForNode(0, 1, 0, 0, std::nullopt)), CHIP_NO_ERROR);
    EXPECT_EQ(table.Size(), MATTER_BINDING_TABLE_SIZE);
    iter = table.begin();
    for (uint8_t i = 0; i < MATTER_BINDING_TABLE_SIZE - 1; i++)
    {
        ++iter;
    }
    EXPECT_EQ(iter->nodeId, 1u);
    EXPECT_EQ(iter.GetIndex(), 1u);
    ++iter;
    EXPECT_EQ(iter, table.end());
    iter = table.begin();
    EXPECT_EQ(table.RemoveAt(iter), CHIP_NO_ERROR);
    EXPECT_EQ(table.Size(), MATTER_BINDING_TABLE_SIZE - 1);
    EXPECT_EQ(iter, table.begin());
    EXPECT_EQ(iter.GetIndex(), 2u);
    EXPECT_EQ(iter->nodeId, 2u);
    EXPECT_EQ(table.GetAt(0).type, MATTER_UNUSED_BINDING);
}

TEST(TestBindingTable, TestPersistentStorage)
{
    chip::TestPersistentStorageDelegate testStorage;
    BindingTable table;
    chip::Optional<chip::ClusterId> cluster = chip::MakeOptional<chip::ClusterId>(static_cast<chip::ClusterId>(UINT16_MAX + 6));
    std::vector<EmberBindingTableEntry> expected = {
        EmberBindingTableEntry::ForNode(0, 0, 0, 0, std::nullopt),
        EmberBindingTableEntry::ForNode(1, 1, 0, 0, cluster.std_optional()),
        EmberBindingTableEntry::ForGroup(2, 2, 0, std::nullopt),
        EmberBindingTableEntry::ForGroup(3, 3, 0, cluster.std_optional()),
    };
    table.SetPersistentStorage(&testStorage);
    EXPECT_EQ(table.Add(expected[0]), CHIP_NO_ERROR);
    EXPECT_EQ(table.Add(expected[1]), CHIP_NO_ERROR);
    EXPECT_EQ(table.Add(expected[2]), CHIP_NO_ERROR);
    EXPECT_EQ(table.Add(expected[3]), CHIP_NO_ERROR);
    VerifyRestored(testStorage, expected);

    // Verify storage untouched if add fails
    testStorage.AddPoisonKey(chip::DefaultStorageKeyAllocator::BindingTableEntry(4).KeyName());
    EXPECT_NE(table.Add(EmberBindingTableEntry::ForNode(4, 4, 0, 0, std::nullopt)), CHIP_NO_ERROR);
    VerifyRestored(testStorage, expected);
    testStorage.ClearPoisonKeys();

    // Verify storage untouched if removing head fails
    testStorage.AddPoisonKey(chip::DefaultStorageKeyAllocator::BindingTable().KeyName());
    auto iter = table.begin();
    EXPECT_NE(table.RemoveAt(iter), CHIP_NO_ERROR);
    VerifyTableSame(table, expected);
    testStorage.ClearPoisonKeys();
    VerifyRestored(testStorage, expected);

    // Verify storage untouched if removing other nodes fails
    testStorage.AddPoisonKey(chip::DefaultStorageKeyAllocator::BindingTableEntry(0).KeyName());
    iter = table.begin();
    ++iter;
    EXPECT_NE(table.RemoveAt(iter), CHIP_NO_ERROR);
    VerifyTableSame(table, expected);
    testStorage.ClearPoisonKeys();
    VerifyRestored(testStorage, expected);

    // Verify removing head
    iter = table.begin();
    EXPECT_EQ(table.RemoveAt(iter), CHIP_NO_ERROR);
    VerifyTableSame(table, { expected[1], expected[2], expected[3] });
    VerifyRestored(testStorage, { expected[1], expected[2], expected[3] });

    // Verify removing other nodes
    ++iter;
    EXPECT_EQ(table.RemoveAt(iter), CHIP_NO_ERROR);
    VerifyTableSame(table, { expected[1], expected[3] });
    VerifyRestored(testStorage, { expected[1], expected[3] });
}

} // namespace
