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

#pragma once

#include "CoreMinimal.h"
#include "BodyPart.h"
#include "ClothingSlotType.h"
#include "Components/ActorComponent.h"
#include "ClothingManager.generated.h"

class AItemPickup;
class UGlobalSaveGameData;
class AClothingPickup;
class UClothingItemInstance;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnClothingChangeSignature, UClothingItemInstance*, ClothingItemInstance);

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class NAKEDDESIRE_API UClothingManager : public UActorComponent
{
	GENERATED_BODY()

public:
	UClothingManager();
	
	virtual void BeginPlay() override;

	UPROPERTY(BlueprintReadWrite, Category = "Clothing Manager|Clothing")
	USkeletalMeshComponent* RootMesh = nullptr;
	
	UPROPERTY(BlueprintAssignable)
	FOnClothingChangeSignature OnClothingEquip;
	
	UPROPERTY(BlueprintAssignable)
	FOnClothingChangeSignature OnClothingUnequip;

	UPROPERTY(BlueprintAssignable)
	FOnClothingChangeSignature OnClothingDropped;
	
	void PutOnClothing(UClothingItemInstance* ClothingItemInstance);
	void DropClothing(const EClothingSlotType ClothingType);
	bool IsClothingTypeOn(const EClothingSlotType ClothingType);
	void TakeClothing(UClothingItemInstance* ClothingItemInstance);

	// Equip an item arriving from off-body storage: writes the EquippedItems save record and
	// applies it to its slot. Slot-occupant / bodysuit-exclusion handling is the caller's job
	// (see UInventorySubsystem::EquipFromWardrobe), so displaced items can be routed deliberately.
	void EquipSlot(UClothingItemInstance* ClothingItemInstance);

	UClothingItemInstance* RemoveClothing(EClothingSlotType ClothingSlotType);

	// Slots that must be vacated when SlotType is equipped, per the bodysuit exclusion rule (§6.5).
	static TArray<EClothingSlotType> GetBodysuitExcludedSlots(EClothingSlotType SlotType);
	void SetClothingSlotItem(const EClothingSlotType ClothingSlotType, UClothingItemInstance* ClothingItemInstance);
	TArray<UClothingItemInstance*> GetEquippedClothing() const;
	UClothingItemInstance* GetSlotClothing(EClothingSlotType SlotType);
	bool IsBodyPartExposed(EBodyPart BodyPart);
	float GetEffectiveCoverage(EBodyPart BodyPart);
	
	UFUNCTION(BlueprintCallable)
	float GetBoobsSupport();

	void HydrateClothing();

	UFUNCTION(BlueprintPure)
	float GetHeelHeight();
	
private:
	void SpawnClothingPickup(UClothingItemInstance* ItemInstance);
	
	UPROPERTY()
	TMap<EClothingSlotType, TObjectPtr<UClothingItemInstance>> EquippedClothing;
	
	UPROPERTY(EditDefaultsOnly, Category = "Clothing")
	TSubclassOf<AItemPickup> ItemPickupActor;
};
