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

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "InventoryComponent.h"
#include "InventorySlotWidget.generated.h"

class UImage;
class UProgressBar;
class UTextBlock;

/**
 * Le curseur est entre sur cette case, ou en est sorti.
 *
 * Un delegue et non un pointeur vers la grille : la barre rapide pose les
 * memes cases sans etre un UInventoryWidget, et elle a autant besoin du survol
 * depuis que l'inventaire affiche un panneau de detail.
 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInventorySlotHoverChanged, int32, SlotIndex, bool, bHovered);

/**
 * Une case de la grille d'inventaire : une icone et une quantite.
 *
 * Volontairement passive pour l'affichage : elle ne va jamais chercher
 * l'information elle-meme, c'est la grille parente qui lui pousse son contenu
 * via SetSlot(). Elle est en revanche autonome pour le glisser-deposer, parce
 * que c'est elle qui recoit les evenements souris.
 */
UCLASS(Abstract)
class EMBERWILD_API UInventorySlotWidget : public UUserWidget
{
	GENERATED_BODY()

public:
	virtual void NativeConstruct() override;

	/** Appele une fois a la creation : dit a la case qui elle represente. */
	void InitSlot(UInventoryComponent* InInventory, int32 InSlotIndex);

	/** Le conteneur qui a cree cette case s'y abonne pour suivre le survol. */
	UPROPERTY()
	FOnInventorySlotHoverChanged OnHoverChanged;

	/** Affiche le contenu d'un slot, ou se vide si le slot est vide. */
	UFUNCTION(BlueprintCallable, Category = "Inventaire")
	void SetSlot(const FInventorySlot& InSlot);

	/**
	 * Transforme cette instance en fantome de glisser : le fond de case
	 * disparait pour ne laisser flotter que l'objet lui-meme.
	 */
	void ConfigureAsDragVisual();

	/** Affiche ou masque le cadre de selection (barre rapide). */
	UFUNCTION(BlueprintCallable, Category = "Inventaire")
	void SetSelected(bool bSelected);

	/**
	 * Inventaire vers lequel le CLIC DROIT envoie le contenu de cette case.
	 *
	 * Nul en temps normal : hors de l'ecran de coffre il n'existe aucun "autre
	 * cote" evident, et deviner une destination reviendrait a faire disparaitre
	 * des objets sur un clic malheureux. C'est l'ecran qui sait, et qui pousse.
	 */
	void SetQuickTransferTarget(UInventoryComponent* InTarget);

protected:
	// --- Glisser-deposer ---
	virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	virtual void NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation) override;
	virtual bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;

	// --- Survol, pour que la touche "jeter" sache sur quoi agir ---
	virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;

	/** A nommer exactement "ItemIcon" dans le Widget Blueprint. */
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<UImage> ItemIcon;

	/** A nommer exactement "QuantityText". */
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<UTextBlock> QuantityText;

	/**
	 * Fond de case. BindWidgetOptional et non BindWidget : le Blueprint peut
	 * s'en passer sans casser la compilation, c'est purement decoratif.
	 * Nomme-le "SlotBackground" pour qu'il soit masque pendant le glisser.
	 */
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UWidget> SlotBackground;

	/**
	 * Cadre affiche quand la case est le slot actif de la barre rapide.
	 * Optionnel : la grille d'inventaire ne s'en sert jamais.
	 */
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UWidget> SelectionBorder;

	/**
	 * Petite barre d'usure en bas de la case, pour les objets a usages
	 * multiples. Masquee automatiquement sur tout le reste.
	 * A nommer "UsesBar" dans le Widget Blueprint.
	 */
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UProgressBar> UsesBar;

	/** Opacite du fantome qui suit le curseur pendant le glisser. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inventaire", meta = (ClampMin = "0.05", ClampMax = "1.0"))
	float DragVisualOpacity = 0.85f;

	/** Opacite de la case d'origine tant que le glisser est en cours. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inventaire", meta = (ClampMin = "0.0", ClampMax = "1.0"))
	float DraggedSlotOpacity = 0.3f;

private:
	/** Rebranche l'opacite normale, que le glisser ait abouti ou non. */
	UFUNCTION()
	void HandleDragFinished(UDragDropOperation* Operation);

	TWeakObjectPtr<UInventoryComponent> OwningInventory;

	/** Destination du clic droit. Voir SetQuickTransferTarget(). */
	TWeakObjectPtr<UInventoryComponent> QuickTransferTarget;

	int32 SlotIndex = INDEX_NONE;

	/** Dernier contenu recu, pour construire le fantome de glisser. */
	FInventorySlot CachedSlot;

	/** Vrai si cette instance est un fantome et non une vraie case de la grille. */
	bool bIsDragVisual = false;
};
