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

#include "Primitives/TTS/InworldTTSTypes.h"

#include "InworldRuntimeSettings.h"
#include "InworldRuntimeUtils.h"

THIRD_PARTY_INCLUDES_START
#include "InworldRuntimeLibrary/inworld.h"
THIRD_PARTY_INCLUDES_END

DEFINE_LOG_CATEGORY(LogInworldTTS);

namespace inworld
{

void Convert(const FInworldLocalTTSCreationConfig& In, inworld::LocalTTSConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	// Local TTS not supported
#endif
}

void Convert(const FInworldRemoteTTSCreationConfig& In, inworld::RemoteTTSConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.api_key({TCHAR_TO_UTF8(*GetInworldRuntimeApiKey())});
	switch (In.Provider)
	{
		case EInworldRemoteTTSProvider::INWORLD:
			inworld::Convert(In.InworldSpeechSynthesisConfig, *Out.synthesis_config()->inworld_config());
			break;
		case EInworldRemoteTTSProvider::ELEVEN_LABS:
			inworld::Convert(In.ElevenLabsSpeechSynthesisConfig, *Out.synthesis_config()->eleven_labs_config());
			break;
	}
#endif
}

void Convert(const FInworldSpeechSynthesisPostprocessingConfig& In, inworld::SpeechSynthesisPostprocessingConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.sample_rate(In.SampleRate);
#endif
}

void Convert(const FInworldSpeechSynthesisInferenceConfig& In, inworld::SpeechSynthesisInferenceConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.temperature(In.Temperature);
	Out.speaking_rate(In.SpeakingRate);
#endif
}

void Convert(const FInworldTTSSpeechSynthesisConfig& In, inworld::InworldSpeechSynthesisConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.model_id(TCHAR_TO_UTF8(*In.ModelId));
	inworld::Convert(In.SpeechSynthesisInferenceConfig, *Out.inference());
	inworld::Convert(In.SpeechSynthesisPostprocessingConfig, *Out.postprocessing());
#endif
}

void Convert(const EElevenLabsTTSOutputFormat& In, FString& Out)
{
	switch (In)
	{
		case EElevenLabsTTSOutputFormat::MP3_22050_32:
			Out = TEXT("MP3_22050_32");
			break;

			// TODO: Support additional output format options
			// case EElevenLabsTTSOutputFormat::MP3_44100_32:
			//	Out = TEXT("MP3_44100_32");
			//	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_64:
			//	Out = TEXT("MP3_44100_64");
			//	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_96:
			//	Out = TEXT("MP3_44100_96");
			//	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_128:
			//	Out = TEXT("MP3_44100_128");
			//	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_192:
			//	Out = TEXT("MP3_44100_192");
			//	break;
	}
}

void Convert(const FElevenLabsTTSSpeechSynthesisConfig& In, inworld::ElevenLabsSpeechSynthesisConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.query_params()->enable_logging(In.EnableLogging);
	switch (In.OutputFormat)
	{
		case EElevenLabsTTSOutputFormat::MP3_22050_32:
			Out.query_params()->output_format(inworld::QueryParams::OutputFormat::MP3_22050_32);
			break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_32:
			// 	Out.query_params()->output_format(inworld::QueryParams::OutputFormat::MP3_44100_32);
			// 	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_64:
			// 	Out.query_params()->output_format(inworld::QueryParams::OutputFormat::MP3_44100_64);
			// 	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_96:
			// 	Out.query_params()->output_format(inworld::QueryParams::OutputFormat::MP3_44100_96);
			// 	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_128:
			// 	Out.query_params()->output_format(inworld::QueryParams::OutputFormat::MP3_44100_128);
			// 	break;
			// case EElevenLabsTTSOutputFormat::MP3_44100_192:
			// 	Out.query_params()->output_format(inworld::QueryParams::OutputFormat::MP3_44100_192);
			// 	break;
	}

	Out.request_params()->model_id({TCHAR_TO_UTF8(*In.ModelId)});
	switch (In.TextNormalization)
	{
		case EElevenLabsTTSTextNormalization::AUTO:
			Out.request_params()->apply_text_normalization(inworld::RequestParams::TextNormalization::AUTO);
			break;
		case EElevenLabsTTSTextNormalization::ON:
			Out.request_params()->apply_text_normalization(inworld::RequestParams::TextNormalization::ON);
			break;
		case EElevenLabsTTSTextNormalization::OFF:
			Out.request_params()->apply_text_normalization(inworld::RequestParams::TextNormalization::OFF);
			break;
	}
#endif
}

void Convert(const FInworldVoice& In, inworld::Voice& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.id({TCHAR_TO_UTF8(*In.Id)});
	if (In.bHasLanguage)
	{
		inworld::Language language;
		inworld::Convert(In.Language, language);
		Out.language()->set_value(language);
	}
#endif
}

void Convert(const inworld::Voice& In, FInworldVoice& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.Id = FString(UTF8_TO_TCHAR(In.id().c_str()));

	if (In.language()->has_value())
	{
		Out.bHasLanguage = true;
		inworld::Convert(In.language()->get_value(), Out.Language);
	}
	else
	{
		Out.bHasLanguage = false;
	}
#endif
}

void Convert(const FInworldTTSNodeExecutionConfig& In, inworld::TTSNodeExecutionConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.tts_component_id({TCHAR_TO_UTF8(*FString("TTS_").Append(In.TTSComponentId))});
	inworld::Convert(In.Voice, *Out.voice());

	if (In.bOverrideSpeechSynthesisConfig)
	{
		inworld::SpeechSynthesisConfig speech_synthesis_config;
		if (In.Provider == EInworldRemoteTTSProvider::INWORLD)
		{
			inworld::Convert(In.InworldSpeechSynthesisConfig, *speech_synthesis_config.inworld_config());
		}
		else if (In.Provider == EInworldRemoteTTSProvider::ELEVEN_LABS)
		{
			inworld::Convert(In.ElevenLabsSpeechSynthesisConfig, *speech_synthesis_config.eleven_labs_config());
		}
		Out.synthesis_config()->set_value(speech_synthesis_config);
	}
#endif
}

}	 // namespace inworld
