/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 *
 * Use of this source code is governed by the Inworld.ai Software Development Kit License Agreement
 * that can be found in the LICENSE.md file or at https://www.inworld.ai/sdk-license
 */

#pragma once

#include "InworldRuntimeTypes.h"
#include "Logging/LogMacros.h"

namespace inworld
{
class STTInterface;
}

#include "InworldSTTTypes.generated.h"

INWORLDRUNTIME_API DECLARE_LOG_CATEGORY_EXTERN(LogInworldSTT, Log, All);

/**
 * @struct FInworldSpeechRecognitionConfig
 * @brief Configuration structure for speech recognition settings.
 *
 * This structure defines parameters for speech-to-text processing,
 * including optional language specification for improved recognition accuracy.
 */
USTRUCT(BlueprintType)
struct FInworldSpeechRecognitionConfig
{
	GENERATED_BODY()

	/** Whether to specify a particular language for recognition */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|SST",
		Meta = (ToolTip = "Whether to specify a particular language for recognition"))
	bool bHasLanguage{false};

	/** The language to use for speech recognition */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|SST",
		Meta = (EditCondition = "bHasLanguage", EditConditionHides, ToolTip = "The language to use for speech recognition"))
	EInworldLanguage Language{EInworldLanguage::ENGLISH};
};

/**
 * @struct FInworldLocalSTTCreationConfig
 * @brief Configuration for creating local speech-to-text instances.
 *
 * This structure defines the parameters required for setting up local STT processing,
 * including compute host selection, model specification, and recognition settings.
 */
USTRUCT(BlueprintType)
struct FInworldLocalSTTCreationConfig
{
	GENERATED_BODY()

	/** The local compute device to use for STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "The local compute device to use for STT processing"))
	EInworldLocalComputeHost LocalComputeHost{EInworldLocalComputeHost::CPU};

	/** The STT model to use for speech recognition */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|SST",
		Meta = (GetOptions = "InworldRuntimeSettings.GetLocalSTTModels", NoResetToDefault,
			ToolTip = "The STT model to use for speech recognition"))
	FString Model{"ggml-base.en.bin"};

	/** Speech recognition configuration settings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Speech recognition configuration settings"))
	FInworldSpeechRecognitionConfig SpeechRecognitionConfig;
};

/**
 * @struct FInworldRemoteSTTCreationConfig
 * @brief Configuration for creating remote speech-to-text instances.
 *
 * This structure defines the parameters required for setting up remote STT processing,
 * including speech recognition configuration for cloud-based services.
 */
USTRUCT(BlueprintType)
struct FInworldRemoteSTTCreationConfig
{
	GENERATED_BODY()

	/** Speech recognition configuration settings for remote STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Speech recognition configuration settings for remote STT processing"))
	FInworldSpeechRecognitionConfig SpeechRecognitionConfig;
};

/**
 * @struct FInworldSTTCreationConfig
 * @brief Main configuration structure for creating STT instances.
 *
 * This structure defines whether to use local or remote STT processing
 * and contains the appropriate sub-configuration for the selected compute host.
 */
USTRUCT(BlueprintType)
struct FInworldSTTCreationConfig
{
	GENERATED_BODY()

	/** Whether to use local or remote compute host for STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Whether to use local or remote compute host for STT processing"))
	EInworldComputeHost ComputeHost{EInworldComputeHost::REMOTE};

	/** Configuration for local STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		meta = (EditCondition = "ComputeHost == EInworldComputeHost::LOCAL", EditConditionHides,
			ToolTip = "Configuration for local STT processing"))
	FInworldLocalSTTCreationConfig LocalCreationConfig;

	/** Configuration for remote STT processing (currently disabled) */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		meta = (EditCondition = "false", EditConditionHides,
			ToolTip = "Configuration for remote STT processing (currently disabled)"))
	FInworldRemoteSTTCreationConfig RemoteCreationConfig;
};

/**
 * @struct FInworldStreamSpeechRecognitionConfig
 * @brief Configuration for streaming speech recognition operations.
 *
 * This structure extends basic speech recognition configuration with streaming-specific
 * parameters such as silence detection thresholds for real-time processing.
 */
USTRUCT(BlueprintType)
struct FInworldStreamSpeechRecognitionConfig
{
	GENERATED_BODY()

	/** Base speech recognition configuration settings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Base speech recognition configuration settings"))
	FInworldSpeechRecognitionConfig SpeechRecognitionConfig;

	/** Silence threshold in milliseconds before ending speech recognition */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (Units = "Milliseconds", ToolTip = "Silence threshold in milliseconds before ending speech recognition"))
	int32 SilenceThresholdMs = 1500;
};

/**
 * @struct FInworldLocalStreamingSTTCreationConfig
 * @brief Configuration for creating local streaming speech-to-text instances.
 *
 * This structure defines the parameters required for setting up local streaming STT processing,
 * including compute host selection, model specification, and streaming recognition settings.
 */
USTRUCT(BlueprintType)
struct FInworldLocalStreamingSTTCreationConfig
{
	GENERATED_BODY()

	/** The local compute device to use for streaming STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "The local compute device to use for streaming STT processing"))
	EInworldLocalComputeHost LocalComputeHost{EInworldLocalComputeHost::CPU};

	/** The STT model to use for streaming speech recognition */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (GetOptions = "InworldRuntimeSettings.GetLocalSTTModels", NoResetToDefault,
			ToolTip = "The STT model to use for streaming speech recognition"))
	FString Model{"ggml-base.en.bin"};

	/** Streaming speech recognition configuration settings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Streaming speech recognition configuration settings"))
	FInworldStreamSpeechRecognitionConfig StreamSpeechRecognitionConfig;
};

/**
 * @struct FInworldRemoteStreamingSTTCreationConfig
 * @brief Configuration for creating remote streaming speech-to-text instances.
 *
 * This structure defines the parameters required for setting up remote streaming STT processing,
 * including streaming recognition configuration for cloud-based services.
 */
USTRUCT(BlueprintType)
struct FInworldRemoteStreamingSTTCreationConfig
{
	GENERATED_BODY()

	/** Streaming speech recognition configuration settings for remote STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Streaming speech recognition configuration settings for remote STT processing"))
	FInworldStreamSpeechRecognitionConfig StreamSpeechRecognitionConfig;
};

/**
 * @struct FInworldStreamingSTTCreationConfig
 * @brief Main configuration structure for creating streaming STT instances.
 *
 * This structure defines whether to use local or remote streaming STT processing
 * and contains the appropriate sub-configuration for the selected compute host.
 */
USTRUCT(BlueprintType)
struct FInworldStreamingSTTCreationConfig
{
	GENERATED_BODY()

	/** Whether to use local or remote compute host for streaming STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		Meta = (ToolTip = "Whether to use local or remote compute host for streaming STT processing"))
	EInworldComputeHost ComputeHost{EInworldComputeHost::REMOTE};

	/** Configuration for local streaming STT processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		meta = (EditCondition = "ComputeHost == EInworldComputeHost::LOCAL", EditConditionHides,
			ToolTip = "Configuration for local streaming STT processing"))
	FInworldLocalStreamingSTTCreationConfig LocalCreationConfig;

	/** Configuration for remote streaming STT processing (currently disabled) */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|STT",
		meta = (EditCondition = "false", EditConditionHides,
			ToolTip = "Configuration for remote streaming STT processing (currently disabled)"))
	FInworldRemoteStreamingSTTCreationConfig RemoteCreationConfig;
};

/** Native delegate called when STT primitive creation completes with interface access */
DECLARE_DELEGATE_OneParam(FOnInworldSTTPrimitiveCreatedNative, TSharedPtr<inworld::STTInterface> /*InworldSpeechToText*/);

/**
 * @struct FInworldSTTNodeExecutionConfig
 * @brief Runtime execution configuration for STT nodes.
 *
 * This structure defines the runtime parameters for STT node execution,
 * including streaming mode selection and component ID configuration.
 */
USTRUCT(BlueprintType)
struct FInworldSTTNodeExecutionConfig
{
	GENERATED_BODY()

	/** Whether to use streaming STT processing instead of batch processing */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|STT",
		Meta = (ToolTip = "Whether to use streaming STT processing instead of batch processing"))
	bool bStreamed{false};

	/** The STT component ID to use for batch processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Inworld|STT",
		Meta = (GetOptions = "InworldRuntimeSettings.GetSTTIds", EditCondition = "!bStreamed", EditConditionHides,
			ToolTip = "The STT component ID to use for batch processing"))
	FString STTComponentId{"Default"};

	/** The streaming STT component ID to use for streaming processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Inworld|STT",
		Meta = (GetOptions = "InworldRuntimeSettings.GetStreamingSTTIds", EditCondition = "bStreamed", EditConditionHides,
			ToolTip = "The streaming STT component ID to use for streaming processing"))
	FString StreamingSTTComponentId{"Default"};
};

namespace inworld
{

class SpeechRecognitionConfig;
/**
 * @brief Converts Unreal speech recognition configuration to internal configuration.
 * @param In The Unreal speech recognition configuration to convert
 * @param Out The internal speech recognition configuration to populate
 */
void Convert(const FInworldSpeechRecognitionConfig& In, inworld::SpeechRecognitionConfig& Out);

class LocalSTTConfig;
/**
 * @brief Converts Unreal local STT creation configuration to internal configuration.
 * @param In The Unreal local STT creation configuration to convert
 * @param Out The internal local STT configuration to populate
 */
void Convert(const FInworldLocalSTTCreationConfig& In, inworld::LocalSTTConfig& Out);

class RemoteSTTConfig;
/**
 * @brief Converts Unreal remote STT creation configuration to internal configuration.
 * @param In The Unreal remote STT creation configuration to convert
 * @param Out The internal remote STT configuration to populate
 */
void Convert(const FInworldRemoteSTTCreationConfig& In, inworld::RemoteSTTConfig& Out);

class StreamSpeechRecognitionConfig;
/**
 * @brief Converts Unreal streaming speech recognition configuration to internal configuration.
 * @param In The Unreal streaming speech recognition configuration to convert
 * @param Out The internal streaming speech recognition configuration to populate
 */
void Convert(const FInworldStreamSpeechRecognitionConfig& In, inworld::StreamSpeechRecognitionConfig& Out);

class LocalStreamingSTTConfig;
/**
 * @brief Converts Unreal local streaming STT creation configuration to internal configuration.
 * @param In The Unreal local streaming STT creation configuration to convert
 * @param Out The internal local streaming STT configuration to populate
 */
void Convert(const FInworldLocalStreamingSTTCreationConfig& In, inworld::LocalStreamingSTTConfig& Out);

class RemoteStreamingSTTConfig;
/**
 * @brief Converts Unreal remote streaming STT creation configuration to internal configuration.
 * @param In The Unreal remote streaming STT creation configuration to convert
 * @param Out The internal remote streaming STT configuration to populate
 */
void Convert(const FInworldRemoteStreamingSTTCreationConfig& In, inworld::RemoteStreamingSTTConfig& Out);

class STTNodeExecutionConfig;
/**
 * @brief Converts Unreal STT node execution configuration to internal configuration.
 * @param In The Unreal STT node execution configuration to convert
 * @param Out The internal STT node execution configuration to populate
 */
void Convert(const FInworldSTTNodeExecutionConfig& In, inworld::STTNodeExecutionConfig& Out);
}	 // namespace inworld
