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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "MainMenuPlayerController.generated.h"

class AMenuCameraSpot;
class UConfirmDialogWidget;
class UMainMenuWidget;
class UScreenFadeComponent;
class USettingsMenuWidget;

/**
 * Ce qu'on fait une fois l'ecran devenu noir.
 *
 * Quitter n'y figure pas : la sortie est seche, sans fondu, une fois la
 * confirmation obtenue.
 */
enum class EMenuPendingAction : uint8
{
	None,
	StartGame
};

/**
 * Controller du menu principal. Il ne possede aucun pawn : il pose simplement
 * sa vue sur une AMenuCameraSpot tiree au hasard et affiche le menu par-dessus.
 *
 * Comme dans le jeu, l'UI vit sur le controller et pas sur un acteur du monde.
 */
UCLASS()
class SURVIVAL_PROJET_API AMainMenuPlayerController : public APlayerController
{
	GENERATED_BODY()

public:
	AMainMenuPlayerController();

	/** Fondu au noir, puis chargement de la map de jeu. */
	UFUNCTION(BlueprintCallable, Category = "Menu")
	void StartSoloGame();

	/** Ouvre la demande de confirmation. Ne quitte rien par elle-meme. */
	UFUNCTION(BlueprintCallable, Category = "Menu")
	void QuitGame();

	/** Ouvre l'ecran de reglages par-dessus le menu. */
	UFUNCTION(BlueprintCallable, Category = "Menu")
	void OpenSettings();

protected:
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

	/**
	 * Ta map de jeu.
	 *
	 * TSoftObjectPtr et non une reference dure : une reference dure ferait
	 * charger la map de jeu EN MEME TEMPS que le menu, alors qu'on ne la veut
	 * qu'au clic sur Jouer. C'est l'equivalent d'une Addressable en Unity, par
	 * opposition a un champ public qui tire tout l'asset avec lui.
	 */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu")
	TSoftObjectPtr<UWorld> GameLevel;

	/** Ton WBP_MainMenu. */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu")
	TSubclassOf<UMainMenuWidget> MainMenuClass;

	/**
	 * Ton WBP_ConfirmDialog. Si tu le laisses vide, le bouton Quitter ferme le
	 * jeu directement -- pratique pour tester, mais laisse-le assigne.
	 */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu")
	TSubclassOf<UConfirmDialogWidget> QuitDialogClass;

	/** La question posee avant de fermer le jeu. */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu")
	FText QuitDialogMessage;

	/** Ton WBP_Settings, exactement le meme que celui du menu de pause. */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu")
	TSubclassOf<USettingsMenuWidget> SettingsMenuClass;

	/** Fondu d'arrivee sur le menu, au lancement du jeu. */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu", meta = (ClampMin = "0.1"))
	float OpeningFadeDuration = 1.5f;

	/** Fondu de depart, quand on quitte le menu pour la partie. */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Menu", meta = (ClampMin = "0.1"))
	float LeaveFadeDuration = 1.f;

	/** Le fondu, partage avec AFpsPlayerController. Assigne-lui ton WBP_Fade. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Menu")
	TObjectPtr<UScreenFadeComponent> ScreenFade;

	UPROPERTY(Transient, BlueprintReadOnly, Category = "Menu")
	TObjectPtr<UMainMenuWidget> MainMenu;

	UPROPERTY(Transient, BlueprintReadOnly, Category = "Menu")
	TObjectPtr<UConfirmDialogWidget> QuitDialog;

	UPROPERTY(Transient, BlueprintReadOnly, Category = "Menu")
	TObjectPtr<USettingsMenuWidget> SettingsMenu;

private:
	/** Tire un angle de vue au hasard, en evitant celui du dernier passage. */
	AMenuCameraSpot* PickCameraSpot();

	/** Le fondu vient de se terminer : on execute l'action mise de cote. */
	UFUNCTION()
	void HandleFadeFinished();

	/** Oui : on ferme le jeu, immediatement. */
	UFUNCTION()
	void HandleQuitConfirmed();

	/** Non : on referme la boite et on rend la main au menu. */
	UFUNCTION()
	void HandleQuitCancelled();

	/** L'ecran de reglages demande a se fermer : on rend la main au menu. */
	UFUNCTION()
	void HandleSettingsCloseRequested();

	/** Ferme le jeu sans rien demander. */
	void CloseGame();

	EMenuPendingAction PendingAction = EMenuPendingAction::None;
};
