#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "HyperTwistUX/HyperTwistPlayerSettings.h"

#include "HyperTwistPlayerControllerBase.generated.h"

class UHyperTwistPauseMenuWidget;
class UHyperTwistCoachAssistantWidget;
class UHyperTwistDictationCaptureComponent;
class IHttpRequest;
class UAudioComponent;
class USoundWaveProcedural;

UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API AHyperTwistPlayerControllerBase : public APlayerController
{
	GENERATED_BODY()

public:
	AHyperTwistPlayerControllerBase();

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Navigation")
	bool bEnableGlobalPauseMenu = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Navigation")
	int32 PauseMenuZOrder = 900;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Navigation")
	TSubclassOf<UHyperTwistPauseMenuWidget> PauseMenuWidgetClass;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Navigation")
	TObjectPtr<UHyperTwistPauseMenuWidget> ActivePauseMenuWidget = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Coach")
	bool bEnableGlobalAssistantPanel = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Coach")
	int32 AssistantPanelZOrder = 700;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Coach")
	TSubclassOf<UHyperTwistCoachAssistantWidget> AssistantPanelWidgetClass;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Coach")
	TObjectPtr<UHyperTwistCoachAssistantWidget> ActiveAssistantPanelWidget = nullptr;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Speech")
	TObjectPtr<UHyperTwistDictationCaptureComponent> GlobalDictationCapture = nullptr;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Navigation")
	bool ShowPauseMenu();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Navigation")
	void HidePauseMenu();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Navigation")
	void ReturnToMainMenu();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Navigation")
	void QuitToDesktop();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Coach")
	bool ShowAssistantPanel();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Coach")
	void HideAssistantPanel();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Coach")
	void ToggleAssistantPanel();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Coach")
	bool IsAssistantPanelOpen() const;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech")
	bool BeginGlobalDictation();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech")
	bool EndGlobalDictation();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech")
	void CancelGlobalDictation();

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech")
	void ToggleGlobalDictation();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech")
	bool IsGlobalDictationActive() const;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Voice")
	bool NarrateCoachResponse(const FString& ResponseText);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Voice")
	void StopCoachNarration();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Settings")
	const FHyperTwistPlayerPreferences& GetPlayerPreferences() const;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Settings")
	void ReloadAndApplyPlayerPreferences(bool bApplyGraphicsSettings = false);

protected:
	virtual FString GetPauseMenuTitle() const;
	virtual FString GetPauseMenuSubtitle() const;
	virtual void PrepareForModalUi();
	void ApplyGameAndUiInputMode();

	UFUNCTION()
	void HandlePauseShortcut();

	UFUNCTION()
	void HandleMainMenuShortcut();

	UFUNCTION()
	void HandleAssistantShortcut();

	UFUNCTION()
	void HandleAssistantCloseRequested();

	UFUNCTION()
	void HandleGlobalDictationPressed();

	UFUNCTION()
	void HandleGlobalDictationReleased();

	UFUNCTION()
	void HandleGlobalDictationStateChanged(
		const FString& Status,
		bool bError
	);

	UFUNCTION()
	void HandleGlobalDictationTranscriptReady(const FString& Transcript);

	UFUNCTION()
	void HandleCoachNarrationFinished();

	UFUNCTION()
	void HandlePauseResumeRequested();

	UFUNCTION()
	void HandlePauseMainMenuRequested();

	UFUNCTION()
	void HandlePauseQuitRequested();

	FHyperTwistPlayerPreferences PlayerPreferences;
	bool bToggleDictationCaptureActive = false;

private:
	void HandleCoachNarrationResponse(
		bool bTransportSucceeded,
		int32 StatusCode,
		const TArray<uint8>& AudioBytes
	);
	bool TryPlayCoachNarration(const TArray<uint8>& AudioBytes);
	void ReleaseCoachNarrationAudio(bool bStopPlayback);
	void ReportCoachNarrationStatus(const FString& Status, bool bError);

	TSharedPtr<IHttpRequest, ESPMode::ThreadSafe> ActiveCoachNarrationRequest;

	UPROPERTY(Transient)
	TObjectPtr<UAudioComponent> ActiveCoachNarrationAudioComponent = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USoundWaveProcedural> ActiveCoachNarrationSoundWave = nullptr;
};
