#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "HyperTwistRecognition/HyperTwistRecognitionTypes.h"
#include "HyperTwistTraining/HyperTwistTrainingTypes.h"
#include "HyperTwistSpeechLibrary.generated.h"

class UAudioComponent;

UENUM(BlueprintType)
enum class EHyperTwistManagedAudioCategory : uint8
{
	Music,
	Effects,
	Voice
};

UCLASS()
class UNREALHYPERTWIST_API UHyperTwistSpeechLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech", meta = (WorldContext = "WorldContextObject"))
	static bool StartDictationSession(
		UObject* WorldContextObject,
		FString& OutError,
		bool bDuckAudio = true,
		float DuckVolumeMultiplier = 0.15f
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech", meta = (WorldContext = "WorldContextObject"))
	static FHyperTwistSpeechTranscriptResult SubmitDictationUtterance(
		UObject* WorldContextObject,
		const FHyperTwistSpeechUtteranceEnvelope& Utterance
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech", meta = (WorldContext = "WorldContextObject"))
	static bool EndDictationSession(
		UObject* WorldContextObject,
		FString& OutError,
		bool bRestoreAudio = true
	);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech", meta = (WorldContext = "WorldContextObject"))
	static FHyperTwistTrainingCompanionSpeechSessionState GetActiveDictationSessionState(
		UObject* WorldContextObject
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Audio")
	static void RegisterManagedAudioComponent(
		UAudioComponent* AudioComponent,
		bool bTreatAsSpeechAudio = false
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Audio")
	static void RegisterCategorizedAudioComponent(
		UAudioComponent* AudioComponent,
		EHyperTwistManagedAudioCategory Category
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Audio")
	static void UnregisterManagedAudioComponent(UAudioComponent* AudioComponent);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Audio")
	static int32 ApplyManagedAudioCategoryVolumes(
		float MusicVolume,
		float EffectsVolume,
		float VoiceVolume
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Audio")
	static int32 DuckManagedAudioComponents(float DuckVolumeMultiplier = 0.15f);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Audio")
	static int32 RestoreManagedAudioComponents();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech|Audio")
	static int32 GetManagedAudioComponentCount();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech|Voice")
	static TArray<FHyperTwistVoiceProfileSummary> ListVoiceProfiles(
		UObject* ContextObject,
		bool bUseMockVoiceClient = false
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Voice")
	static FHyperTwistNarrationSynthesisResult SynthesizeNarration(
		UObject* ContextObject,
		const FHyperTwistNarrationSynthesisRequest& Request,
		bool bUseMockVoiceClient = false
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech|Voice")
	static TArray<uint8> Synthesize(
		UObject* ContextObject,
		const FString& Text,
		const FString& VoiceId,
		bool bUseMockVoiceClient = false
	);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech|Audio")
	static TArray<uint8> ExtractPcm16PayloadFromAudioBytes(
		const TArray<uint8>& AudioBytes,
		const FString& AudioEncoding
	);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech|Voice")
	static FHyperTwistVoiceServiceHealth GetVoiceServiceHealth(
		UObject* ContextObject,
		bool bUseMockVoiceClient = false
	);
};
