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

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CraftingRecipeDataAsset.generated.h"

class UItemDataAsset;
class UTexture2D;

/**
 * Poste de travail necessaire pour realiser une recette.
 *
 * Ce n'est PAS un filtre d'affichage : c'est une condition de realisation.
 * Le UCraftingComponent tient la liste des stations dont le joueur dispose a
 * l'instant t -- {Hands} tout seul, {Hands, Workbench} devant un etabli -- et
 * une recette n'est realisable que si la sienne s'y trouve. Le filtre de
 * l'interface est une notion separee, purement visuelle : melanger les deux
 * finirait par rendre un craft impossible parce qu'un bouton d'affichage est
 * mal positionne, et ce genre de bug ne se comprend jamais sur le moment.
 *
 * Fourneau et feu de cuisson n'ont volontairement PAS leur entree ici : ils ne
 * passent par aucun menu. Ce sont des acteurs poses dans le monde, facon Raft,
 * ou l'on depose une ressource et ou l'on voit le mesh changer d'etat. Leur
 * donnee et leur file d'attente leur appartiendront, une recette de menu n'a
 * rien a y faire.
 */
UENUM(BlueprintType)
enum class ECraftingStation : uint8
{
	Hands,
	Workbench,

	// Sentinelle, jamais assignee a une recette. Elle sert a parcourir l'enum
	// pour construire les boutons de filtre sans avoir a les enumerer a la main.
	Count UMETA(Hidden)
};

/** Une ligne de cout : tant d'exemplaires de tel objet. */
USTRUCT(BlueprintType)
struct FCraftIngredient
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe")
	TObjectPtr<UItemDataAsset> Item = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe", meta = (ClampMin = "1"))
	int32 Quantity = 1;
};

/**
 * Une recette : ce qu'il faut, ce que ca donne, ou ca se fabrique.
 *
 * Un asset par recette, comme un DataAsset par objet. Trois comportements de
 * craft n'existeront jamais : la recette est de la donnee pure, c'est le
 * composant qui l'execute.
 *
 * Elle ne contient aucun etat -- ni "deja decouverte", ni "en cours de
 * fabrication". Le jour ou les recettes se debloqueront en jeu, la liste des
 * RecipeId connus vivra dans la sauvegarde, pas ici : sinon decouvrir une
 * recette la debloquerait pour toutes les parties a la fois.
 */
UCLASS(BlueprintType)
class EMBERWILD_API UCraftingRecipeDataAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
	/**
	 * Identifiant stable, independant du nom de l'asset.
	 * Servira a la sauvegarde des recettes decouvertes : renommer un asset ne
	 * doit pas faire oublier au joueur ce qu'il avait debloque.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe")
	FName RecipeId;

	/** Ce que la fabrication consomme. Une recette sans cout est acceptee (objet gratuit). */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe")
	TArray<FCraftIngredient> Ingredients;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe")
	TObjectPtr<UItemDataAsset> ResultItem;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe", meta = (ClampMin = "1"))
	int32 ResultQuantity = 1;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe")
	ECraftingStation RequiredStation = ECraftingStation::Hands;

	// Pas de duree de fabrication ici : le craft de menu est instantane, comme
	// dans Valheim ou Raft. La fabrication qui prend du temps est celle des
	// postes qui travaillent SANS le joueur, et ceux-la ne sont pas des recettes.

	/**
	 * Nom affiche, quand celui du resultat ne suffit pas.
	 * Laisse vide dans l'immense majorite des cas : dupliquer le nom de l'objet
	 * dans la recette, c'est se garantir deux textes qui divergeront un jour.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe|Display")
	FText DisplayNameOverride;

	/** Icone affichee dans la grille de craft. Vide = celle du resultat. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Recipe|Display")
	TObjectPtr<UTexture2D> IconOverride;

	/** Le nom a afficher, override compris. Passe toujours par ici, jamais par ResultItem directement. */
	UFUNCTION(BlueprintPure, Category = "Recipe")
	FText GetDisplayName() const;

	/** L'icone a afficher, override compris. */
	UFUNCTION(BlueprintPure, Category = "Recipe")
	UTexture2D* GetIcon() const;

#if WITH_EDITOR
	/**
	 * Une recette sans resultat ne planterait pas : elle ne ferait simplement
	 * RIEN, en consommant les ingredients. C'est exactement le genre de bug qu'on
	 * cherche pendant une heure -- autant que l'editeur le refuse a la sauvegarde.
	 */
	virtual EDataValidationResult IsDataValid(class FDataValidationContext& Context) const override;
#endif
};
