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

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "InputCoreTypes.h"
#include "KeyCaptureWidget.generated.h"

class UButton;
class UTextBlock;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnKeyCaptured, FKey, CapturedKey);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnKeyCaptureCancelled);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnKeyConflictAnswered, bool, bConfirmed);

/** Ce que le voile attend a un instant donne. */
UENUM()
enum class EKeyCaptureState : uint8
{
	/** Ferme. */
	Idle,

	/** Ouvert, en attente d'une touche. Les boutons sont replies. */
	Capturing,

	/** Ouvert, la touche est prise : on demande quoi faire. Les boutons apparaissent. */
	Conflict
};

/**
 * Le voile de remappage, en deux temps : "Appuie sur une touche", puis
 * eventuellement "cette touche est deja prise, on la vole ?".
 *
 * Les deux etapes vivent dans le MEME widget et non dans deux ecrans successifs.
 * Le conflit fait partie du geste de remappage : refermer le voile pour ouvrir
 * une boite par-dessus produirait un clignotement et ferait perdre le fil de ce
 * qu'on etait en train de modifier. UConfirmDialogWidget garde les questions
 * generiques -- reinitialiser, abandonner une partie, valider une resolution.
 *
 * Classe Abstract : on cree un WBP_KeyCapture qui en herite.
 */
UCLASS(Abstract)
class EMBERWILD_API UKeyCaptureWidget : public UUserWidget
{
	GENERATED_BODY()

public:
	UKeyCaptureWidget(const FObjectInitializer& ObjectInitializer);

	virtual void NativeOnInitialized() override;
	virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override;
	virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;

	UPROPERTY(BlueprintAssignable, Category = "Reglages")
	FOnKeyCaptured OnKeyCaptured;

	UPROPERTY(BlueprintAssignable, Category = "Reglages")
	FOnKeyCaptureCancelled OnCaptureCancelled;

	UPROPERTY(BlueprintAssignable, Category = "Reglages")
	FOnKeyConflictAnswered OnConflictAnswered;

	/** Affiche le voile, ecrit la consigne, replie les boutons et prend le focus. */
	UFUNCTION(BlueprintCallable, Category = "Reglages")
	void BeginCapture(const FText& ActionLabel);

	/**
	 * Bascule le voile deja ouvert sur la question de conflit.
	 *
	 * Ne referme rien : c'est tout l'interet d'avoir garde un seul widget.
	 */
	UFUNCTION(BlueprintCallable, Category = "Reglages")
	void ShowConflict(const FText& Message);

	UFUNCTION(BlueprintCallable, Category = "Reglages")
	void EndCapture();

	UFUNCTION(BlueprintPure, Category = "Reglages")
	EKeyCaptureState GetCaptureState() const { return State; }

protected:
	/** Optionnel : un voile dont le texte est fige dans le Blueprint reste valide. */
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UTextBlock> PromptText;

	/**
	 * Boutons de la seule etape de conflit. Replies pendant la capture : les
	 * afficher inertes inviterait a cliquer alors qu'on attend une touche.
	 */
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UButton> ConfirmButton;

	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UButton> CancelButton;

	/** Doit contenir {0}, remplace par le nom de l'action en cours de remappage. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Reglages")
	FText PromptFormat;

private:
	UFUNCTION()
	void HandleConfirmClicked();

	UFUNCTION()
	void HandleCancelClicked();

	/** Facteur commun a NativeOnKeyDown et NativeOnMouseButtonDown. */
	FReply CaptureKey(const FKey& Key);

	/** Affiche ou replie les deux boutons selon l'etat. */
	void UpdateButtonVisibility();

	EKeyCaptureState State = EKeyCaptureState::Idle;
};
