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

#include "InworldRuntimeTypes.h"

THIRD_PARTY_INCLUDES_START
#include "InworldRuntimeLibrary/inworld.h"
THIRD_PARTY_INCLUDES_END

namespace inworld
{

void Convert(const EInworldLanguage& In, inworld::Language& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	switch (In)
	{
		case EInworldLanguage::ARABIC:
			Out = inworld::Language::Arabic();
			break;
		case EInworldLanguage::CHINESE:
			Out = inworld::Language::Chinese();
			break;
		case EInworldLanguage::DANISH:
			Out = inworld::Language::Danish();
			break;
		case EInworldLanguage::DUTCH:
			Out = inworld::Language::Dutch();
			break;
		case EInworldLanguage::ENGLISH:
			Out = inworld::Language::English();
			break;
		case EInworldLanguage::FINNISH:
			Out = inworld::Language::Finnish();
			break;
		case EInworldLanguage::FRENCH:
			Out = inworld::Language::French();
			break;
		case EInworldLanguage::GERMAN:
			Out = inworld::Language::German();
			break;
		case EInworldLanguage::HEBREW:
			Out = inworld::Language::Hebrew();
			break;
		case EInworldLanguage::HINDI:
			Out = inworld::Language::Hindi();
			break;
		case EInworldLanguage::INDONESIAN:
			Out = inworld::Language::Indonesian();
			break;
		case EInworldLanguage::ITALIAN:
			Out = inworld::Language::Italian();
			break;
		case EInworldLanguage::JAPANESE:
			Out = inworld::Language::Japanese();
			break;
		case EInworldLanguage::KOREAN:
			Out = inworld::Language::Korean();
			break;
		case EInworldLanguage::MALAY:
			Out = inworld::Language::Malay();
			break;
		case EInworldLanguage::NORWEGIAN:
			Out = inworld::Language::Norwegian();
			break;
		case EInworldLanguage::POLISH:
			Out = inworld::Language::Polish();
			break;
		case EInworldLanguage::PORTUGUESE:
			Out = inworld::Language::Portuguese();
			break;
		case EInworldLanguage::RUSSIAN:
			Out = inworld::Language::Russian();
			break;
		case EInworldLanguage::SPANISH:
			Out = inworld::Language::Spanish();
			break;
		case EInworldLanguage::SWEDISH:
			Out = inworld::Language::Swedish();
			break;
		case EInworldLanguage::THAI:
			Out = inworld::Language::Thai();
			break;
		case EInworldLanguage::TURKISH:
			Out = inworld::Language::Turkish();
			break;
		case EInworldLanguage::UKRAINIAN:
			Out = inworld::Language::Ukrainian();
			break;
		case EInworldLanguage::VIETNAMESE:
			Out = inworld::Language::Vietnamese();
			break;
		default:
			break;
	}
#endif
}

void Convert(const inworld::Language& In, EInworldLanguage& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	auto lang = In.lang();

	if (lang == inworld::Language::Arabic().lang())
	{
		Out = EInworldLanguage::ARABIC;
	}
	else if (lang == inworld::Language::Chinese().lang())
	{
		Out = EInworldLanguage::CHINESE;
	}
	else if (lang == inworld::Language::Danish().lang())
	{
		Out = EInworldLanguage::DANISH;
	}
	else if (lang == inworld::Language::Dutch().lang())
	{
		Out = EInworldLanguage::DUTCH;
	}
	else if (lang == inworld::Language::English().lang())
	{
		Out = EInworldLanguage::ENGLISH;
	}
	else if (lang == inworld::Language::Finnish().lang())
	{
		Out = EInworldLanguage::FINNISH;
	}
	else if (lang == inworld::Language::French().lang())
	{
		Out = EInworldLanguage::FRENCH;
	}
	else if (lang == inworld::Language::German().lang())
	{
		Out = EInworldLanguage::GERMAN;
	}
	else if (lang == inworld::Language::Hebrew().lang())
	{
		Out = EInworldLanguage::HEBREW;
	}
	else if (lang == inworld::Language::Hindi().lang())
	{
		Out = EInworldLanguage::HINDI;
	}
	else if (lang == inworld::Language::Indonesian().lang())
	{
		Out = EInworldLanguage::INDONESIAN;
	}
	else if (lang == inworld::Language::Italian().lang())
	{
		Out = EInworldLanguage::ITALIAN;
	}
	else if (lang == inworld::Language::Japanese().lang())
	{
		Out = EInworldLanguage::JAPANESE;
	}
	else if (lang == inworld::Language::Korean().lang())
	{
		Out = EInworldLanguage::KOREAN;
	}
	else if (lang == inworld::Language::Malay().lang())
	{
		Out = EInworldLanguage::MALAY;
	}
	else if (lang == inworld::Language::Norwegian().lang())
	{
		Out = EInworldLanguage::NORWEGIAN;
	}
	else if (lang == inworld::Language::Polish().lang())
	{
		Out = EInworldLanguage::POLISH;
	}
	else if (lang == inworld::Language::Portuguese().lang())
	{
		Out = EInworldLanguage::PORTUGUESE;
	}
	else if (lang == inworld::Language::Russian().lang())
	{
		Out = EInworldLanguage::RUSSIAN;
	}
	else if (lang == inworld::Language::Spanish().lang())
	{
		Out = EInworldLanguage::SPANISH;
	}
	else if (lang == inworld::Language::Swedish().lang())
	{
		Out = EInworldLanguage::SWEDISH;
	}
	else if (lang == inworld::Language::Thai().lang())
	{
		Out = EInworldLanguage::THAI;
	}
	else if (lang == inworld::Language::Turkish().lang())
	{
		Out = EInworldLanguage::TURKISH;
	}
	else if (lang == inworld::Language::Ukrainian().lang())
	{
		Out = EInworldLanguage::UKRAINIAN;
	}
	else if (lang == inworld::Language::Vietnamese().lang())
	{
		Out = EInworldLanguage::VIETNAMESE;
	}
#endif
}

void Convert(const EInworldLanguage& In, FString& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	switch (In)
	{
		case EInworldLanguage::ARABIC:
			Out = UTF8_TO_TCHAR(inworld::Language::Arabic().lang().c_str());
			break;
		case EInworldLanguage::CHINESE:
			Out = UTF8_TO_TCHAR(inworld::Language::Chinese().lang().c_str());
			break;
		case EInworldLanguage::DANISH:
			Out = UTF8_TO_TCHAR(inworld::Language::Danish().lang().c_str());
			break;
		case EInworldLanguage::DUTCH:
			Out = UTF8_TO_TCHAR(inworld::Language::Dutch().lang().c_str());
			break;
		case EInworldLanguage::ENGLISH:
			Out = UTF8_TO_TCHAR(inworld::Language::English().lang().c_str());
			break;
		case EInworldLanguage::FINNISH:
			Out = UTF8_TO_TCHAR(inworld::Language::Finnish().lang().c_str());
			break;
		case EInworldLanguage::FRENCH:
			Out = UTF8_TO_TCHAR(inworld::Language::French().lang().c_str());
			break;
		case EInworldLanguage::GERMAN:
			Out = UTF8_TO_TCHAR(inworld::Language::German().lang().c_str());
			break;
		case EInworldLanguage::HEBREW:
			Out = UTF8_TO_TCHAR(inworld::Language::Hebrew().lang().c_str());
			break;
		case EInworldLanguage::HINDI:
			Out = UTF8_TO_TCHAR(inworld::Language::Hindi().lang().c_str());
			break;
		case EInworldLanguage::INDONESIAN:
			Out = UTF8_TO_TCHAR(inworld::Language::Indonesian().lang().c_str());
			break;
		case EInworldLanguage::ITALIAN:
			Out = UTF8_TO_TCHAR(inworld::Language::Italian().lang().c_str());
			break;
		case EInworldLanguage::JAPANESE:
			Out = UTF8_TO_TCHAR(inworld::Language::Japanese().lang().c_str());
			break;
		case EInworldLanguage::KOREAN:
			Out = UTF8_TO_TCHAR(inworld::Language::Korean().lang().c_str());
			break;
		case EInworldLanguage::MALAY:
			Out = UTF8_TO_TCHAR(inworld::Language::Malay().lang().c_str());
			break;
		case EInworldLanguage::NORWEGIAN:
			Out = UTF8_TO_TCHAR(inworld::Language::Norwegian().lang().c_str());
			break;
		case EInworldLanguage::POLISH:
			Out = UTF8_TO_TCHAR(inworld::Language::Polish().lang().c_str());
			break;
		case EInworldLanguage::PORTUGUESE:
			Out = UTF8_TO_TCHAR(inworld::Language::Portuguese().lang().c_str());
			break;
		case EInworldLanguage::RUSSIAN:
			Out = UTF8_TO_TCHAR(inworld::Language::Russian().lang().c_str());
			break;
		case EInworldLanguage::SPANISH:
			Out = UTF8_TO_TCHAR(inworld::Language::Spanish().lang().c_str());
			break;
		case EInworldLanguage::SWEDISH:
			Out = UTF8_TO_TCHAR(inworld::Language::Swedish().lang().c_str());
			break;
		case EInworldLanguage::THAI:
			Out = UTF8_TO_TCHAR(inworld::Language::Thai().lang().c_str());
			break;
		case EInworldLanguage::TURKISH:
			Out = UTF8_TO_TCHAR(inworld::Language::Turkish().lang().c_str());
			break;
		case EInworldLanguage::UKRAINIAN:
			Out = UTF8_TO_TCHAR(inworld::Language::Ukrainian().lang().c_str());
			break;
		case EInworldLanguage::VIETNAMESE:
			Out = UTF8_TO_TCHAR(inworld::Language::Vietnamese().lang().c_str());
			break;
		default:
			break;
	}
#endif
}

}	 // namespace inworld

void FInworldGraphExecutionHistory::AddError(const FString& ErrorMessage)
{
	ErrorList.Add(ErrorMessage);
}

const FString FInworldGraphExecutionHistory::GetLastError() const
{
	if (ErrorList.Num())
	{
		return ErrorList[ErrorList.Num() - 1];
	}
	return FString();
}

const FInworldNodeHistory* FInworldGraphExecutionHistory::GetLastNode() const
{
	for (int i = NodeHistory.Num() - 1; i >= 0; --i)
	{
		const FInworldNodeHistory& Node = NodeHistory[i];
		if (!Node.ParentSpanId.IsEmpty())
		{
			return &Node;
		}
	}
	return nullptr;
}

const FInworldNodeHistory* FInworldGraphExecutionHistory::GetSlowestNode() const
{
	const FInworldNodeHistory* BestNode = nullptr;
	double WorstTime = 0;
	for (const FInworldNodeHistory& Node : NodeHistory)
	{
		if (Node.DurationInMilliSeconds > WorstTime)
		{
			WorstTime = Node.DurationInMilliSeconds;
			BestNode = &Node;
		}
	}

	return BestNode;
}
