/*********************************************************************
 * \file   AssetContainer.cpp
 *
 * \author Romain BOULLARD
 * \date   July 2026
 *********************************************************************/
#include <Engine/Asset/AssetContainer.hpp>

#include <AssetsForTesting/Asset/AssetA.hpp>
#include <gtest/gtest.h>

namespace Bigfoot
{
class AssetContainerFixture: public ::testing::Test
{
  protected:
    AssetContainer<AssetA> m_containerA;
};

/****************************************************************************************/

TEST_F(AssetContainerFixture, Has_ShouldReturnTrueIfTheContainerHasTheAsset)
{
    AssetA asset1;
    std::ignore = m_containerA.Insert(asset1);
    EXPECT_TRUE(m_containerA.Has(asset1.GetHeader().uuid));
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, Has_ShouldReturnFalseIfTheContainerDoesNotHaveTheAsset)
{
    AssetA asset1;
    EXPECT_FALSE(m_containerA.Has(asset1.GetHeader().uuid));
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, AcquireHandle_ShouldReturnTheAssociatedContainerHandle)
{
    AssetA asset1;
    std::ignore = m_containerA.Insert(asset1);

    const ContainerHandle& handle = m_containerA.AcquireContainerHandle(asset1.GetHeader().uuid);
    EXPECT_EQ(static_cast<const AssetA*>(handle.GetAsset())->GetHeader().uuid, asset1.GetHeader().uuid);
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, AcquireHandle_ShouldCreateTheAssociatedContainerHandleIfItDoesNotExists)
{
    AssetA asset1;

    const ContainerHandle& handle = m_containerA.AcquireContainerHandle(asset1.GetHeader().uuid);
    EXPECT_EQ(handle.GetAsset(), nullptr);
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, Insert_ShouldReturnValidAndUniqueSlotKeyOnInsert)
{
    AssetA asset1;
    const SlotMapKey slotKey = m_containerA.Insert(asset1);
    EXPECT_TRUE(slotKey.Valid());
    EXPECT_NE(slotKey, m_containerA.Insert());
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, Insert_ShouldReturnTheSameSlotKeyInCaseOfDuplicatedUUID)
{
    AssetA asset;
    const SlotMapKey slotKey = m_containerA.Insert(asset);
    EXPECT_EQ(slotKey, m_containerA.Insert(asset));
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, Get_ShouldReturnTheAssetWithTheSlotKey)
{
    AssetA asset;
    const SlotMapKey slotKey = m_containerA.Insert(asset);

    EXPECT_EQ(m_containerA.Get(slotKey)->GetHeader().uuid, asset.GetHeader().uuid);
    EXPECT_EQ(const_cast<const AssetContainer<AssetA>&>(m_containerA).Get(slotKey)->GetHeader().uuid,
              asset.GetHeader().uuid);
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, Get_ShouldReturnNullptrIfSlotKeyNotInContainer)
{
    EXPECT_EQ(m_containerA.Get(SlotMapKey {1, 0}), nullptr);
    EXPECT_EQ(const_cast<const AssetContainer<AssetA>&>(m_containerA).Get(SlotMapKey {1, 0}), nullptr);
}

/****************************************************************************************/

TEST_F(AssetContainerFixture, Remove_ShouldRemoveTheAsset)
{
    AssetA asset;
    const SlotMapKey slotKey = m_containerA.Insert(asset);

    m_containerA.Remove(asset.GetHeader().uuid);

    EXPECT_EQ(m_containerA.Get(slotKey), nullptr);
    EXPECT_FALSE(m_containerA.Has(asset.GetHeader().uuid));
}
}   // namespace Bigfoot
