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

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interactable.generated.h"

/**
 * Classe technique requise par Unreal. On ne la manipule jamais directement,
 * elle sert uniquement au systeme de reflection : c'est elle qu'on passe a
 * Implements<UInteractable>() et a Execute_XXX().
 */
UINTERFACE(MinimalAPI, BlueprintType)
class UInteractable : public UInterface
{
	GENERATED_BODY()
};

/**
 * A implementer par tout ce avec quoi le joueur peut interagir : objets a
 * ramasser, portes, coffres, etablis, plantes a recolter.
 *
 * Les fonctions sont des BlueprintNativeEvent : une classe C++ surcharge
 * XXX_Implementation(), un Blueprint surcharge l'evenement du meme nom.
 * Les deux fonctionnent, et l'appelant n'a pas a savoir lequel des deux
 * il a en face -- c'est tout l'interet de passer par une interface.
 *
 * IMPORTANT : pour appeler ces fonctions depuis l'exterieur, utilise
 * IInteractable::Execute_Interact(Actor, Interactor) et jamais
 * Actor->Interact() directement. Seul le wrapper Execute_ sait router
 * l'appel vers une implementation Blueprint.
 */
class EMBERWILD_API IInteractable
{
	GENERATED_BODY()

public:
	/**
	 * Texte affiche au joueur quand il vise l'objet ("Ramasser", "Ouvrir"...).
	 * Renvoie du FText et non du FString : c'est le type localisable d'Unreal,
	 * indispensable si tu traduis le jeu un jour.
	 *
	 * Interactor est fourni parce que le texte depend souvent de CELUI qui vise
	 * et d'ou il vise : un feu de camp nomme l'emplacement precis qu'on regarde,
	 * un coffre verrouille annonce quelle cle il attend. Sans lui, l'objet
	 * devrait aller chercher le joueur local par un chemin detourne -- ce qui
	 * marche exactement jusqu'au jour ou il y a deux joueurs.
	 */
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
	FText GetInteractionPrompt(AActor* Interactor) const;
	virtual FText GetInteractionPrompt_Implementation(AActor* Interactor) const { return FText::GetEmpty(); }

	/**
	 * Permet de refuser l'interaction selon le contexte : porte verrouillee,
	 * inventaire plein, competence manquante. Renvoyer false empeche l'objet
	 * d'etre meme selectionne par le composant d'interaction.
	 */
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
	bool CanInteract(AActor* Interactor) const;
	virtual bool CanInteract_Implementation(AActor* Interactor) const { return true; }

	/** L'interaction elle-meme. Interactor est le pawn du joueur. */
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
	void Interact(AActor* Interactor);
	virtual void Interact_Implementation(AActor* Interactor) {}

	/** Le joueur commence a viser l'objet : surbrillance, son, animation. */
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
	void OnBeginFocus();
	virtual void OnBeginFocus_Implementation() {}

	/** Le joueur ne vise plus l'objet. */
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
	void OnEndFocus();
	virtual void OnEndFocus_Implementation() {}
};
