#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"

#include "HyperTwistDictationCaptureComponent.generated.h"

class IVoiceCapture;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
	FHyperTwistDictationStateChangedSignature,
	const FString&,
	Status,
	bool,
	bError
);

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
	FHyperTwistDictationTranscriptReadySignature,
	const FString&,
	Transcript
);

UCLASS(ClassGroup = (HyperTwist), BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API UHyperTwistDictationCaptureComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UHyperTwistDictationCaptureComponent();

	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
	virtual void TickComponent(
		float DeltaTime,
		ELevelTick TickType,
		FActorComponentTickFunction* ThisTickFunction
	) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech")
	bool BeginCapture(FString& OutFailureReason);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech")
	bool EndCapture(FString& OutTranscript, FString& OutFailureReason);

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

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

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech")
	FString GetStatus() const;

	UPROPERTY(BlueprintAssignable, Category = "HyperTwist|Speech")
	FHyperTwistDictationStateChangedSignature OnStateChanged;

	UPROPERTY(BlueprintAssignable, Category = "HyperTwist|Speech")
	FHyperTwistDictationTranscriptReadySignature OnTranscriptReady;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Speech")
	int32 CaptureSampleRateHz = 16000;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Speech")
	int32 CaptureChannelCount = 1;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Speech")
	float MaximumCaptureSeconds = 60.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Speech")
	float AudioDuckMultiplier = 0.15f;

private:
	bool DrainCaptureBuffer(FString& OutFailureReason);
	bool WriteTransientWaveFile(
		const FString& FilePath,
		const TArray<uint8>& PcmBytes
	) const;
	void ResetCaptureState(bool bCloseDictationSession);
	void SetStatus(const FString& NewStatus, bool bError = false);
	FString BuildTransientCapturePath() const;

	TSharedPtr<IVoiceCapture> ActiveVoiceCapture;
	TArray<uint8> CapturedPcmBytes;
	FString ActiveUtteranceId;
	FString ActiveCapturePath;
	FString CurrentStatus = TEXT("Dictation ready.");
	double CaptureStartedAtSeconds = 0.0;
	bool bCaptureActive = false;
};
