// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "InventoryWidget.generated.h"

class UInventoryComponent;
class UInventorySlotWidget;
class UUniformGridPanel;

/**
 * Grille d'inventaire. Cree ses cases dynamiquement a partir du nombre de
 * slots du composant, et se remet a jour uniquement quand l'inventaire change.
 *
 * Le nombre de cases n'est PAS fige : quand un sac ajoutera des slots, la
 * grille s'agrandira toute seule au prochain rafraichissement.
 */
UCLASS(Abstract)
class SURVIVAL_PROJET_API UInventoryWidget : public UUserWidget
{
	GENERATED_BODY()

public:
	virtual void NativeConstruct() override;
	virtual void NativeDestruct() override;

	/** Reconstruit si necessaire, puis pousse le contenu dans chaque case. */
	UFUNCTION(BlueprintCallable, Category = "Inventaire")
	void Refresh();

	/** Index de la case sous le curseur, ou INDEX_NONE. */
	UFUNCTION(BlueprintPure, Category = "Inventaire")
	int32 GetHoveredSlotIndex() const { return HoveredSlotIndex; }

	/** Appele par les cases quand le curseur entre ou sort. */
	void NotifySlotHovered(int32 Index, bool bHovered);

	/**
	 * (Re)branche le widget sur l'inventaire du pawn actuellement possede.
	 * Indispensable apres un respawn : le nouveau pawn a un nouveau composant,
	 * et l'ancien abonnement pointerait vers un objet detruit.
	 */
	void BindToOwningPawn();

protected:
	/** A nommer exactement "SlotGrid" dans le Widget Blueprint. */
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<UUniformGridPanel> SlotGrid;

	/** Le widget de case a instancier : ton WBP_InventorySlot. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inventaire")
	TSubclassOf<UInventorySlotWidget> SlotWidgetClass;

	/** Nombre de cases par ligne. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inventaire", meta = (ClampMin = "1"))
	int32 ColumnCount = 6;

protected:
	/**
	 * Absorbe les depots qui ne visent aucune case. Sans ca, lacher un objet
	 * sur le fond du panneau declencherait OnDragCancelled -- et si un jour on
	 * y branche le drop au sol, le joueur jetterait son butin par accident.
	 */
	virtual bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;

private:
	UFUNCTION()
	void HandleInventoryChanged();

	/** Cree ou supprime des cases pour coller au nombre de slots. */
	void RebuildGrid(int32 DesiredCount);

	/** Retrouve l'inventaire du pawn possede. */
	UInventoryComponent* ResolveInventory() const;

	TWeakObjectPtr<UInventoryComponent> BoundInventory;

	int32 HoveredSlotIndex = INDEX_NONE;

	/** UPROPERTY obligatoire : sans ca le GC collecterait les cases. */
	UPROPERTY(Transient)
	TArray<TObjectPtr<UInventorySlotWidget>> SlotWidgets;
};
