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


#include "ClothingVisualsComponent.h"

#include "ClothingItemDefinition.h"
#include "ClothingItemInstance.h"
#include "ClothingManager.h"
#include "Components/SkeletalMeshComponent.h"
#include "Materials/MaterialInstance.h"

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

void UClothingVisualsComponent::Initialize(USkeletalMeshComponent* InBodyMesh, UClothingManager* InClothingManager)
{
	BodyMesh = InBodyMesh;
	ClothingManager = InClothingManager;

	if (!ClothingManager)
		return;

	ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &UClothingVisualsComponent::HandleClothingEquip);
	ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &UClothingVisualsComponent::HandleClothingUnequip);

	for (const UClothingItemInstance* Equipped : ClothingManager->GetEquippedClothing())
	{
		Apply(Equipped);
	}
}

void UClothingVisualsComponent::Apply(const UClothingItemInstance* ClothingItemInstance)
{
	if (!ClothingItemInstance)
		return;

	const UClothingItemDefinition* Definition = ClothingItemInstance->GetClothingItemDefinition();
	if (!Definition)
		return;

	USkeletalMeshComponent* SlotMesh = GetOrCreateSlotMesh(Definition->SlotType);
	if (!SlotMesh)
		return;

	SlotMesh->SetSkeletalMesh(Definition->SkeletalMesh);

	if (Definition->UseLeaderPose)
	{
		SlotMesh->SetLeaderPoseComponent(BodyMesh);
	}

	for (const TPair<FName, UMaterialInstance*>& Material : Definition->Materials)
	{
		SlotMesh->SetMaterialByName(Material.Key, Material.Value);
	}
}

void UClothingVisualsComponent::ClearSlot(EClothingSlotType SlotType)
{
	if (const TObjectPtr<USkeletalMeshComponent>* Found = SlotMeshes.Find(SlotType))
	{
		(*Found)->SetLeaderPoseComponent(nullptr);
		(*Found)->SetSkeletalMesh(nullptr);
	}
}

void UClothingVisualsComponent::HandleClothingEquip(UClothingItemInstance* ClothingItemInstance)
{
	Apply(ClothingItemInstance);
}

void UClothingVisualsComponent::HandleClothingUnequip(UClothingItemInstance* ClothingItemInstance)
{
	if (ClothingItemInstance && ClothingItemInstance->GetClothingItemDefinition())
	{
		ClearSlot(ClothingItemInstance->GetClothingItemDefinition()->SlotType);
	}
}

USkeletalMeshComponent* UClothingVisualsComponent::GetOrCreateSlotMesh(EClothingSlotType SlotType)
{
	if (const TObjectPtr<USkeletalMeshComponent>* Found = SlotMeshes.Find(SlotType))
	{
		return *Found;
	}

	if (!BodyMesh)
		return nullptr;

	const FName ComponentName = *FString::Printf(TEXT("ClothingSlotMesh_%d"), static_cast<int32>(SlotType));
	USkeletalMeshComponent* SlotMesh = NewObject<USkeletalMeshComponent>(GetOwner(), ComponentName);
	SlotMesh->SetupAttachment(BodyMesh);
	SlotMesh->RegisterComponent();
	SlotMeshes.Add(SlotType, SlotMesh);
	return SlotMesh;
}