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

#pragma once

#include "CoreMinimal.h"
#include "InputCoreTypes.h"
#include "SettingsTabWidget.h"
#include "SettingsControlsWidget.generated.h"

class UEnhancedInputUserSettings;
class USettingKeyRowWidget;

/**
 * L'onglet "Touches".
 *
 * Le stockage, la persistance et l'application des surcharges appartiennent a
 * UEnhancedInputUserSettings, natif depuis 5.3 : on n'ecrit ni serialisation ni
 * reconstruction d'IMC. Cet onglet n'est qu'une facade -- afficher les touches
 * courantes, capturer la nouvelle, arbitrer les conflits.
 *
 * PREREQUIS EDITEUR : sans "Enable User Settings" dans Project Settings ->
 * Enhanced Input, et sans Player Mappable Key Settings sur chaque mapping de
 * IMC_Default, toutes les lignes afficheront "Non assignée".
 *
 * Classe Abstract : on cree un WBP_SettingsControls qui en herite.
 */
UCLASS(Abstract)
class EMBERWILD_API USettingsControlsWidget : public USettingsTabWidget
{
	GENERATED_BODY()

public:
	USettingsControlsWidget(const FObjectInitializer& ObjectInitializer);

	virtual void NativeConstruct() override;

	virtual void RefreshFromSettings() override;
	virtual void ResetToDefaults() override;

protected:
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> MoveForwardRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> MoveBackwardRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> MoveLeftRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> MoveRightRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> JumpRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> SprintRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> CrouchRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> InteractRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> UseItemRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> ToggleInventoryRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> ToggleCraftingRow;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<USettingKeyRowWidget> DropItemRow;

	/**
	 * Question posee en cas de conflit. Trois emplacements :
	 *   {0} la touche, {1} l'action qui la possede, {2} l'action qui la reclame.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Reglages")
	FText ConflictMessage;

private:
	UFUNCTION()
	void HandleRebindRequested(FName MappingName);

	UFUNCTION()
	void HandleKeyCaptured(FKey CapturedKey);

	UFUNCTION()
	void HandleConflictAnswered(bool bConfirmed);

	/** Ecrit la touche en attente sur le mapping en attente, puis rafraichit. */
	void ApplyPendingRebind();

	/** Le sous-systeme de reglages d'input du joueur local, ou nullptr. */
	UEnhancedInputUserSettings* GetInputSettings() const;

	/** Toutes les lignes, dans l'ordre d'affichage. Ignore les nulles. */
	TArray<USettingKeyRowWidget*> GetAllRows() const;

	/** La ligne portant ce nom de mapping, ou nullptr. */
	USettingKeyRowWidget* FindRow(FName MappingName) const;

	/**
	 * Donne son identite a une ligne et retient son libelle.
	 *
	 * Le libelle vient du C++ et non du "Display Name" des Player Mappable Key
	 * Settings : ca t'evite de le saisir onze fois dans l'editeur, et ca garde
	 * les textes traduisibles au meme endroit que le reste du menu.
	 */
	void SetupRow(USettingKeyRowWidget* Row, FName MappingName, const FText& Label);

	/** Libelle lisible d'un mapping. Retombe sur l'identifiant si inconnu. */
	FText GetMappingDisplayName(FName MappingName) const;

	/** Libelles retenus a la construction, pour les messages de conflit. */
	TMap<FName, FText> MappingLabels;

	/** Mapping en cours de remappage, et touche capturee en attente d'arbitrage. */
	FName PendingMappingName = NAME_None;

	FKey PendingKey;

	/** Mapping a qui l'on volerait la touche si le joueur confirme. */
	FName ConflictingMappingName = NAME_None;
};
