/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */

#pragma once

#include "CoreMinimal.h"
#include "Graph/InworldData.h"
#include "InworldRuntimeTypes.h"
#include "UObject/NoExportTypes.h"

#include "InworldAudioBuffer.generated.h"

/**
 * @struct FInworldAudioBufferConfig
 * @brief Configuration structure for audio buffer creation and management.
 *
 * This structure defines the parameters used when creating and configuring
 * audio buffers for recording and processing voice data within the Inworld system.
 */
USTRUCT(BlueprintType, Blueprintable)
struct FInworldAudioBufferConfig
{
	GENERATED_BODY()

	/** The sample rate for audio recording in Hz (default: 16000 Hz for optimal voice quality) */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|Audio")
	int32 SampleRate{16000};

	/** Minimum duration in seconds before audio data can be flushed from the buffer */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|Audio")
	float MinAudioDuration{0.f};
};

/** Blueprint delegate called when the audio buffer is flushed with collected audio data */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
	FOnInworldAudioBufferFlush, class UInworldAudioBuffer*, AudioBuffer, const FInworldData_Audio&, Audio);

/** Native delegate called when the audio buffer is flushed with collected audio data */
DECLARE_MULTICAST_DELEGATE_TwoParams(
	FOnInworldAudioBufferFlushNative, class UInworldAudioBuffer* /*AudioBuffer*/, const FInworldData_Audio& /*Audio*/);

/**
 * @class UInworldAudioBuffer
 * @brief Audio buffer for collecting and managing voice recording data.
 *
 * This class provides functionality for buffering audio chunks during voice recording,
 * allowing for efficient collection and processing of audio data before sending it
 * for further processing. It manages sample rate consistency, data accumulation,
 * and provides thread-safe operations for audio data handling.
 *
 * Key features:
 * - Thread-safe audio data collection
 * - Sample rate validation and consistency checking
 * - Minimum duration enforcement before flushing
 * - Event-driven architecture with flush notifications
 */
UCLASS(ClassGroup = (Inworld), NotBlueprintable, BlueprintType)
class INWORLDRUNTIME_API UInworldAudioBuffer final : public UObject
{
	GENERATED_BODY()

public:
	/** Creates a new audio buffer to record voice.
	 *
	 * This function initializes an instance of UInworldAudioBuffer using the provided configuration.
	 * It allows customization of the sample rate and channels.
	 *
	 * @param Config The configuration struct containing sample rate and channels.
	 * Default: SampleRate = 16000, Channels = 1.
	 * @return A pointer to the newly created UInworldAudioBuffer instance.
	 */
	UFUNCTION(BlueprintCallable, Category = "Inworld|Factory", meta = (AutoCreateRefTerm = "Config"))
	static UInworldAudioBuffer* CreateAudioBuffer(const FInworldAudioBufferConfig& Config);

	/** Adds an audio chunk to the audio buffer.
	 *
	 * This function appends the provided audio data to the buffer.
	 * Ensures that the incoming audio chunk matches the buffer's sample rate and channel configuration.
	 * If the chunk is incompatible, the function will abort.
	 *
	 * @param AudioChunk The audio data to add to the buffer. Must match the buffer's sample rate and channels.
	 */
	UFUNCTION(BlueprintCallable, Category = "Inworld|Audio")
	void Add(const FInworldData_Audio& AudioChunk);

	/** Flushes the collected audio data from the buffer.
	 *
	 * If the buffer contains audio data, it constructs an FInworldData_Audio and
	 * broadcasts it via the OnAudioBufferFlush delegate. After broadcasting, the buffer is cleared.
	 * If the buffer is empty, this function does nothing.
	 *
	 * Events: OnAudioBufferFlush
	 */
	UFUNCTION(BlueprintCallable, Category = "Inworld|Audio")
	FInworldData_Audio Flush();

	/** Blueprint delegate called when the buffer is flushed with collected audio data */
	UPROPERTY(BlueprintAssignable)
	FOnInworldAudioBufferFlush OnAudioBufferFlush;

	/** Native delegate called when the buffer is flushed with collected audio data */
	FOnInworldAudioBufferFlushNative OnAudioBufferFlushNative;

protected:
	/** Configuration settings used for this audio buffer instance */
	FInworldAudioBufferConfig AudioBufferConfig;

	/**
	 * @struct FAudioBuffer
	 * @brief Thread-safe internal audio data storage structure.
	 *
	 * This structure encapsulates the raw audio data and provides thread-safe
	 * access through a critical section, ensuring data integrity during
	 * concurrent read/write operations.
	 */
	struct FAudioBuffer
	{
		/** Critical section for thread-safe access to audio data */
		FCriticalSection CriticalSection;

		/** Raw audio data buffer stored as byte array */
		TArray<uint8> Data;
	} AudioBuffer;
};
