// © 2025 Naked People Team. All Rights Reserved.


#include "ClothingManager.h"
#include "ClothingItem.h"
#include "ClothingItemInstance.h"
#include "GameFramework/Character.h"

UClothingManager::UClothingManager()
{
	PrimaryComponentTick.bCanEverTick = false;
}

bool UClothingManager::IsBodyTypeExposed(const EPrivateBodyPartType PrivateBodyPartType)
{
	for (const auto& ClothingSlot : ClothingSlots)
	{
		if (ClothingSlot.ClothingItemInstance && ClothingSlot.ClothingItemInstance->GetClothingItem()->CoveredBodyParts.Contains(PrivateBodyPartType))
		{
			return false;
		}
	}
	
	return true;
}

bool UClothingManager::GetClothingSlotData(const EClothingSlotType ClothingSlotType, FClothingSlotData& OutClothingSlotData)
{
	for (const auto& ClothingSlot : ClothingSlots)
	{
		if (ClothingSlot.ClothingSlotType == ClothingSlotType)
		{
			OutClothingSlotData = ClothingSlot;
			return true;
		}
	}

	return false;
}
void UClothingManager::SetClothingSlotItem(const EClothingSlotType ClothingSlotType, UClothingItemInstance* ClothingItemInstance)
{
	for (FClothingSlotData& ClothingSlot : ClothingSlots)
	{
		if (ClothingSlot.ClothingSlotType == ClothingSlotType)
		{
			ClothingSlot.ClothingItemInstance = ClothingItemInstance;
		}
	}
}

TArray<UClothingItemInstance*> UClothingManager::GetEquippedClothing()
{
	TArray<UClothingItemInstance*> EquippedClothingItems;

	for (FClothingSlotData ClothingSlot : ClothingSlots)
	{
		if (ClothingSlot.ClothingItemInstance)
		{
			EquippedClothingItems.Add(ClothingSlot.ClothingItemInstance);
		}
	}

	return EquippedClothingItems;
}

void UClothingManager::HydrateClothing(UGlobalSaveGameData* SaveGameData)
{
	// for (const FClothingItemSaveData& ClothingItemSaveData : SaveGameData->PlayerClothing)
	// {
	// 	UClothingItemData* ClothingItemData = UClothingItemData::CreateFromSaveData(ClothingItemSaveData);
	// 	PutOnClothing(ClothingItemData);
	// }
}

float UClothingManager::GetHeelHeight()
{
	if (FClothingSlotData ClothingSlotData; GetClothingSlotData(EClothingSlotType::Shoes, ClothingSlotData))
	{
		if (ClothingSlotData.ClothingItemInstance)
		{
			return ClothingSlotData.ClothingItemInstance->GetClothingItem()->ShoesOffset;
		}
	}

	return 0;
}

void UClothingManager::PutOnClothing(UClothingItemInstance* ClothingItemInstance)
{
	if (!ClothingItemInstance)
		return;
	
	const EClothingSlotType ClothingSlotType = ClothingItemInstance->GetClothingItem()->SlotType;

	FClothingSlotData ClothingSlotData;
	GetClothingSlotData(ClothingSlotType, ClothingSlotData);
	
	ClothingSlotData.MeshComponent->SetSkeletalMesh(ClothingItemInstance->GetClothingItem()->SkeletalMesh);
	if (!ClothingItemInstance->GetClothingItem()->Materials.IsEmpty())
	{
		for (const TPair<FName, UMaterialInstance*>& Material : ClothingItemInstance->GetClothingItem()->Materials)
		{
			ClothingSlotData.MeshComponent->SetMaterialByName(Material.Key, Material.Value);
		}
	}
	
	SetClothingSlotItem(ClothingSlotType, ClothingItemInstance);
	if (ClothingItemInstance->GetClothingItem()->UseLeaderPose)
	{
		ClothingSlotData.MeshComponent->SetLeaderPoseComponent(Cast<ACharacter>(GetOwner())->GetMesh());
	}

	OnClothingEquip.Broadcast(ClothingItemInstance);
}

void UClothingManager::TakeClothing(UClothingItemInstance* ClothingItemInstance)
{
	FClothingSlotData ClothingSlotData;
	GetClothingSlotData(ClothingItemInstance->GetClothingItem()->SlotType, ClothingSlotData);
	
	if (ClothingSlotData.ClothingItemInstance->GetClothingItem())
	{
		DropClothing(ClothingItemInstance->GetClothingItem()->SlotType);
	}

	ClothingSlotData.ClothingItemInstance = ClothingItemInstance;
	
	PutOnClothing(ClothingItemInstance);
}

UClothingItemInstance* UClothingManager::RemoveClothing(const EClothingSlotType ClothingSlotType)
{
	FClothingSlotData ClothingSlotData;
	if (!GetClothingSlotData(ClothingSlotType, ClothingSlotData) || !ClothingSlotData.ClothingItemInstance)
	{
		UE_LOG(LogTemp, Error, TEXT("Couldn't find clothing slot"));
		return nullptr;
	}
	
	UClothingItemInstance* ClothingItemInstance = ClothingSlotData.ClothingItemInstance;
	SetClothingSlotItem(ClothingSlotType, nullptr);
	
	USkeletalMeshComponent* MeshComponent = ClothingSlotData.MeshComponent;
	MeshComponent->SetSkeletalMesh(nullptr);

	if (ClothingItemInstance->GetClothingItem()->UseLeaderPose)
	{
		ClothingSlotData.MeshComponent->SetLeaderPoseComponent(nullptr);
	}

	OnClothingUnequip.Broadcast(ClothingItemInstance);

	return ClothingItemInstance;
}

void UClothingManager::DropClothing(const EClothingSlotType ClothingType)
{
	const UClothingItemInstance* ClothingItemInstance = RemoveClothing(ClothingType);
	if (!ClothingItemInstance)
		return;

	OnClothingDropped.Broadcast(ClothingItemInstance);
}

bool UClothingManager::IsClothingTypeOn(const EClothingSlotType ClothingType)
{
	FClothingSlotData ClothingSlotData;
	GetClothingSlotData(ClothingType, ClothingSlotData);
	
	const bool IsTypeOn = ClothingSlotData.ClothingItemInstance != nullptr;
	return IsTypeOn;
}

bool UClothingManager::IsPartiallyNaked()
{
	return IsBodyTypeExposed(EPrivateBodyPartType::BackBottom) || IsBodyTypeExposed(EPrivateBodyPartType::FrontBottom) || IsBodyTypeExposed(EPrivateBodyPartType::FrontTop);
}
