// Discord Rich Presence - plugin made by Mathew Simon.

#pragma once

#include "CoreMinimal.h"
#include "Containers/Ticker.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "DiscordRichPresenceTypes.h"
#include "DiscordRichPresenceSubsystem.generated.h"

class FDiscordIpcConnection;

/**
 * Demarre tout seul avec le jeu : se connecte a Discord, envoie l'activite par defaut
 * definie dans Project Settings > Plugins > Discord Rich Presence, puis se reconnecte
 * automatiquement si Discord est ferme/relance en cours de partie.
 */
UCLASS()
class DISCORDRICHPRESENCE_API UDiscordRichPresenceSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()

public:
	virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;
	virtual void Deinitialize() override;

	/** Raccourci Blueprint : Get Discord Rich Presence. */
	UFUNCTION(BlueprintPure, Category = "Discord", meta = (WorldContext = "WorldContextObject", DisplayName = "Get Discord Rich Presence"))
	static UDiscordRichPresenceSubsystem* Get(const UObject* WorldContextObject);

	/** Remplace toute la presence affichee. */
	UFUNCTION(BlueprintCallable, Category = "Discord")
	void SetActivity(const FDiscordRichPresenceActivity& NewActivity);

	/** Cas courant : ne change que les deux lignes de texte, garde les images. */
	UFUNCTION(BlueprintCallable, Category = "Discord")
	void SetDetailsAndState(const FString& Details, const FString& State);

	/** Met a jour le compteur "(x sur y)". PartySize a 0 masque le compteur. */
	UFUNCTION(BlueprintCallable, Category = "Discord")
	void SetParty(int32 PartySize, int32 PartyMax);

	/** Repart de zero sur le chrono "temps ecoule" (nouvelle partie, respawn, etc.). */
	UFUNCTION(BlueprintCallable, Category = "Discord")
	void ResetElapsedTime();

	/** Retire le jeu du statut Discord (la connexion reste ouverte). */
	UFUNCTION(BlueprintCallable, Category = "Discord")
	void ClearActivity();

	/** Activite en cours (ou en attente d'envoi). */
	UFUNCTION(BlueprintPure, Category = "Discord")
	FDiscordRichPresenceActivity GetCurrentActivity() const { return CurrentActivity; }

	/** Vrai quand Discord est connecte et a valide le handshake. */
	UFUNCTION(BlueprintPure, Category = "Discord")
	bool IsConnectedToDiscord() const;

private:
	bool Tick(float DeltaTime);
	void TryConnect();

	// TSharedPtr et pas TUniquePtr : le deleter est efface a la construction, donc le code
	// genere par UHT n'a pas besoin de la definition complete de FDiscordIpcConnection.
	TSharedPtr<FDiscordIpcConnection> Connection;
	FTSTicker::FDelegateHandle TickerHandle;

	UPROPERTY()
	FDiscordRichPresenceActivity CurrentActivity;

	/** Timestamp Unix du debut de partie, pour le compteur de temps de jeu. */
	int64 StartUnixTime = 0;

	/** Une modification est en attente d'envoi (throttle par MinUpdateIntervalSeconds). */
	bool bActivityDirty = false;

	/** L'activite a ete effacee volontairement : ne pas la re-envoyer au prochain tick. */
	bool bActivityCleared = false;

	double LastSendTime = 0.0;
	double LastConnectAttemptTime = 0.0;
};
