/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */
#include "Primitives/TTS/InworldTTSTasks.h"

#include "InworldRuntimeTypes.h"
#include "InworldRuntimeUtils.h"
#include "Misc/Optional.h"
#include "Misc/Paths.h"
#include "Misc/TVariant.h"
#include "Primitives/TTS/InworldTTSTypes.h"

#include <Interfaces/IPluginManager.h>

THIRD_PARTY_INCLUDES_START
#include "InworldRuntimeLibrary/inworld.h"
THIRD_PARTY_INCLUDES_END

static TVariant<TSharedPtr<inworld::TTSInterface>, FString> CreateTTS(const FInworldLocalTTSCreationConfig& LocalTTSCreationConfig)
{
#define RETURN_ERROR(Error) return TVariant<TSharedPtr<inworld::TTSInterface>, FString>{TInPlaceType<FString>(), Error};
#define RETURN_SUCCESS(Object) \
	return TVariant<TSharedPtr<inworld::TTSInterface>, FString>{TInPlaceType<TSharedPtr<inworld::TTSInterface>>(), Object};

	RETURN_ERROR(FString::Format(TEXT("{0}: Local TTS Not Supported"), {*FString(__func__)}))

#undef RETURN_ERROR
#undef RETURN_SUCCESS
}

static TVariant<TSharedPtr<inworld::TTSInterface>, FString> CreateTTS(
	const FInworldRemoteTTSCreationConfig& RemoteTTSCreationConfig)
{
#define RETURN_ERROR(Error) return TVariant<TSharedPtr<inworld::TTSInterface>, FString>{TInPlaceType<FString>(), Error};
#define RETURN_SUCCESS(Object) \
	return TVariant<TSharedPtr<inworld::TTSInterface>, FString>{TInPlaceType<TSharedPtr<inworld::TTSInterface>>(), Object};

	const FString& RuntimeApiKey{GetInworldRuntimeApiKey()};
	if (RuntimeApiKey.IsEmpty())
	{
		RETURN_ERROR(FString::Format(TEXT("{0}: Inworld Runtime API Key is not set. Check ProjectSettings."), {*FString(__func__)}))
	}

	inworld::RemoteTTSConfig remote_tts_config;
	inworld::Convert(RemoteTTSCreationConfig, remote_tts_config);
	if (const inworld::StatusOr_TTSInterface status_or_tts{inworld::TTSFactory().CreateTTS(remote_tts_config)}; status_or_tts.ok())
	{
		RETURN_SUCCESS(MakeShared<inworld::TTSInterface>(status_or_tts.value()));
	}
	else
	{
		RETURN_ERROR(
			FString::Format(TEXT("{0}: {1}"), {*FString(__func__), UTF8_TO_TCHAR(status_or_tts.status().ToString().c_str())}))
	}

#undef RETURN_ERROR
#undef RETURN_SUCCESS
}

namespace inworld
{
namespace Tasks
{
namespace TTS
{

UE::Tasks::TTask<TVariant<TSharedPtr<inworld::TTSInterface>, FString>> CreateTTSTask(
	const FInworldTTSCreationConfig& TTSCreationConfig)
{
#define RETURN_ERROR(Error) return TVariant<TSharedPtr<inworld::TTSInterface>, FString>{TInPlaceType<FString>(), Error};

	return UE::Tasks::Launch(UE_SOURCE_LOCATION,
		[TTSCreationConfig]()
		{
			switch (TTSCreationConfig.ComputeHost)
			{
				case EInworldComputeHost::LOCAL:
				{
					const FInworldLocalTTSCreationConfig& LocalTTSCreationConfig{TTSCreationConfig.LocalCreationConfig};
					return CreateTTS(LocalTTSCreationConfig);
				}
				break;
				case EInworldComputeHost::REMOTE:
				{
					const FInworldRemoteTTSCreationConfig& RemoteTTSCreationConfig{TTSCreationConfig.RemoteCreationConfig};
					return CreateTTS(RemoteTTSCreationConfig);
				}
				break;
				default:
					RETURN_ERROR(
						FString::Format(TEXT("{0}: Invalid Enum Value: TTSreationConfig.ComputeHost"), {*FString(__func__)}));
			}
		});
#undef RETURN_ERROR
}

}	 // namespace TTS
}	 // namespace Tasks
}	 // namespace inworld
