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

#pragma once

#include "CoreMinimal.h"
#include "Chaos/ChaosEngineInterface.h"
#include "Engine/DataAsset.h"
#include "FootstepSoundsDataAsset.generated.h"

class USoundBase;

/**
 * Les trois allures pour lesquelles le pack livre un son.
 *
 * Les noms sont ceux des fichiers du pack et PAS ceux des etats du jeu, alors
 * que la tentation serait grande de les appeler Crouch / Walk / Sprint. La
 * correspondance est etablie une seule fois, dans UFootstepComponent, et elle
 * n'est pas l'identite : le personnage marche a 400 cm/s, ce qui est deja un
 * trot -- d'ou accroupi = Walk, marche = Jog, sprint = Run. Nommer l'enum
 * d'apres les etats obligerait a ecrire "le son Walk est dans le champ Crouch"
 * dans le Details panel, ce qui est exactement le genre de traduction qu'on
 * finit par se tromper en relisant.
 */
UENUM(BlueprintType)
enum class EFootstepGait : uint8
{
	/** Le pas le plus discret du pack. Utilise quand le personnage est accroupi. */
	Walk,

	/** Allure de marche normale du jeu (WalkSpeed). */
	Jog,

	/** Sprint. */
	Run
};

/**
 * La banque de sons d'UNE surface : les huit cues que le pack fournit pour
 * chacune de ses matieres.
 *
 * Tous les champs sont facultatifs. Une case vide ne produit aucun son et
 * n'est pas une erreur -- c'est ce qui permet de commencer avec trois surfaces
 * remplies et d'ajouter les autres au fil du temps, ou de renoncer aux sons
 * d'arret sans toucher au code.
 */
USTRUCT(BlueprintType)
struct FFootstepSurfaceSounds
{
	GENERATED_BODY()

	// ------------------------------------------------------------------
	// Les pas eux-memes, un par allure.
	// ------------------------------------------------------------------

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Steps")
	TObjectPtr<USoundBase> WalkStep;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Steps")
	TObjectPtr<USoundBase> JogStep;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Steps")
	TObjectPtr<USoundBase> RunStep;

	// ------------------------------------------------------------------
	// Le pas final, joue quand le personnage s'immobilise.
	//
	// Ce n'est pas un ornement : sans lui, une course qui s'arrete coupe la
	// serie de pas net, comme si le personnage s'etait teleporte. Le pack les
	// livre exprès, avec un son plus traine que le pas courant.
	// ------------------------------------------------------------------

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stop")
	TObjectPtr<USoundBase> WalkStop;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stop")
	TObjectPtr<USoundBase> JogStop;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stop")
	TObjectPtr<USoundBase> RunStop;

	// ------------------------------------------------------------------
	// Saut et reception. Une seule variante chacun, quelle que soit l'allure.
	// ------------------------------------------------------------------

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Air")
	TObjectPtr<USoundBase> Jump;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Air")
	TObjectPtr<USoundBase> Land;

	/** Le pas courant d'une allure, ou nullptr si la case est vide. */
	USoundBase* GetStepSound(EFootstepGait Gait) const;

	/** Le pas final d'une allure, ou nullptr si la case est vide. */
	USoundBase* GetStopSound(EFootstepGait Gait) const;
};

/**
 * La table de correspondance surface physique -> banque de sons.
 *
 * Un seul asset a remplir pour tout le jeu, et le SEUL endroit a toucher pour
 * ajouter une matiere. Le composant n'y range aucun etat : il le lit, c'est
 * tout, ce qui permet de le partager entre le joueur, les futurs PNJ et les
 * animaux sans se poser de question.
 *
 * La cle est le SurfaceType declare dans Project Settings > Physics, pas un
 * nom ni un chemin d'asset : c'est le seul identifiant que le moteur nous
 * rende depuis un trace, et il tient dans un octet.
 */
UCLASS(BlueprintType)
class EMBERWILD_API UFootstepSoundsDataAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
	/**
	 * Une entree par matiere du jeu. Les surfaces absentes de cette table
	 * tombent sur DefaultSurface.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Footsteps")
	TMap<TEnumAsByte<EPhysicalSurface>, FFootstepSurfaceSounds> Surfaces;

	/**
	 * Le repli, et il n'est pas facultatif en pratique.
	 *
	 * Un decor n'est jamais tague a 100 % : il restera toujours un rocher de
	 * demo, un mesh importe a la va-vite ou un acteur de test sans materiau. Le
	 * symptome d'un repli vide est un silence total sur ces surfaces, qu'on
	 * confond immediatement avec "le systeme ne marche pas". Mettre ici les
	 * cues de terre est le choix sur.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Footsteps")
	FFootstepSurfaceSounds DefaultSurface;

	/**
	 * Les sons d'une surface, ou DefaultSurface si elle n'est pas dans la table.
	 * Ne rend jamais nullptr : l'appelant n'a qu'a tester les cues elles-memes.
	 */
	const FFootstepSurfaceSounds& GetSurfaceSounds(EPhysicalSurface Surface) const;
};
