// Georgy Treshchev 2026 All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "AEC/RuntimeAECFeature.h"

struct AEC3Instance;
struct AEC3AudioBuffer;

/**
 * WebRTC AEC3 implementation of the AEC modular feature.
 * Uses the opaque C wrapper API, no WebRTC headers are included.
 * Registered automatically when the RuntimeWebRTCAEC plugin module loads.
 */
class RUNTIMEAUDIOIMPORTERWEBRTCAEC3_API FWebRTCAEC3Feature : public FRuntimeAECFeature
{
public:
	FWebRTCAEC3Feature();
	virtual ~FWebRTCAEC3Feature() override;

	//~ Begin FRuntimeAECFeature Interface
	virtual bool Initialize(int32 InSampleRate, int32 InNumChannels) override;
	virtual void Reset() override;
	virtual bool IsInitialized() const override;
	virtual void ProcessRenderAudio(const TArray<float>& RenderPCMData, int32 SampleRate, int32 NumChannels) override;
	virtual bool ProcessCaptureAudio(TArray<float>& CapturePCMData, int32 SampleRate, int32 NumChannels) override;
	virtual void SetStreamDelay(int32 DelayMs) override;
	virtual int32 GetSampleRate() const override;
	virtual int32 GetNumChannels() const override;
	virtual FString GetImplementationName() const override;
	virtual int32 GetExpectedFrameSizePerChannel() const override;
	//~ End FRuntimeAECFeature Interface

private:
	/**
	 * Process a single 10ms frame of render audio through the echo controller.
	 * @param FrameData Pointer to interleaved float samples for one 10ms frame
	 * @param NumSamplesPerChannel Number of samples per channel in this frame
	 */
	void ProcessRenderFrame(const float* FrameData, int32 NumSamplesPerChannel);

	/**
	 * Process a single 10ms frame of capture audio through the echo controller.
	 * @param FrameData Pointer to interleaved float samples for one 10ms frame (modified in place)
	 * @param NumSamplesPerChannel Number of samples per channel in this frame
	 * @return True if processing succeeded
	 */
	bool ProcessCaptureFrame(float* FrameData, int32 NumSamplesPerChannel);

	/**
	 * Convert interleaved float PCM data into a deinterleaved channel buffer format
	 * suitable for the AEC3 audio buffer.
	 */
	void DeinterleaveToAudioBuffer(const float* InterleavedData, int32 NumSamplesPerChannel, AEC3AudioBuffer* Buffer);

	/**
	 * Convert an AEC3 audio buffer back to interleaved float PCM data.
	 */
	void InterleaveFromAudioBuffer(const AEC3AudioBuffer* Buffer, float* InterleavedData, int32 NumSamplesPerChannel);

	/** Opaque AEC3 instance from the C wrapper */
	AEC3Instance* Instance;

	/** Cached render buffer pointer (owned by Instance) */
	AEC3AudioBuffer* RenderAudioBuffer;

	/** Cached capture buffer pointer (owned by Instance) */
	AEC3AudioBuffer* CaptureAudioBuffer;

	/** Accumulated render PCM data when input chunks are not exactly 10ms */
	TArray<float> AccumulatedRenderData;

	/** Accumulated capture PCM data when input chunks are not exactly 10ms */
	TArray<float> AccumulatedCaptureData;

	/** The sample rate the AEC was initialized with */
	int32 SampleRate;

	/** The number of channels the AEC was initialized with */
	int32 NumChannels;

	/** The number of samples per channel in one 10ms frame */
	int32 FrameSizePerChannel;

	/** Whether the AEC processor has been initialized */
	bool bInitialized;

	/** Critical section for thread safety */
	FCriticalSection ProcessingCriticalSection;
};
