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

#include "Primitives/LLM/InworldLLMTypes.h"

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

THIRD_PARTY_INCLUDES_START
#include "InworldRuntimeLibrary/inworld.h"
THIRD_PARTY_INCLUDES_END

DEFINE_LOG_CATEGORY(LogInworldLLM);

namespace inworld
{

void Convert(const FInworldLocalLLMCreationConfig& In, inworld::LocalLLMConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	inworld::Device device{FInworldRuntimeUtils::GetDevice(
		(In.LocalComputeHost == EInworldLocalComputeHost::CPU) ? inworld::DeviceType::kCPU : inworld::DeviceType::kCUDA)};
	Out.device(&device);
	Out.model_path({TCHAR_TO_UTF8(*GetInworldExtrasPath("llm", In.Model))});
#endif
}

void Convert(const FInworldRemoteLLMCreationConfig& In, inworld::RemoteLLMConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.provider({TCHAR_TO_UTF8(*In.Provider)});
	Out.api_key({TCHAR_TO_UTF8(*GetInworldRuntimeApiKey())});
	Out.model_name({TCHAR_TO_UTF8(*In.Model)});
#endif
}

void Convert(const FInworldLLMTextGenerationConfig& In, inworld::TextGenerationConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.max_new_tokens(In.MaxNewTokens);
	Out.max_prompt_length(In.MaxPromptLength);
	Out.temperature(In.Temperature);
	Out.top_p(In.TopP);
	Out.repetition_penalty(In.RepetitionPenalty);
	Out.frequency_penalty(In.FrequencyPenalty);
	Out.presence_penalty(In.PresencePenalty);
	for (const FString& StopSequence : In.StopSequences)
	{
		Out.stop_sequences()->push_back({TCHAR_TO_UTF8(*StopSequence)});
	}
#endif
}

void Convert(const FInworldLLMChatNodeExecutionConfig& In, inworld::LLMChatNodeExecutionConfig& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	Out.llm_component_id({TCHAR_TO_UTF8(*FString("LLM_").Append(In.LLMComponentId))});
	Out.stream(In.bStream);
	inworld::TextGenerationConfig text_generation_config;
	inworld::Convert(In.TextGenerationConfig, text_generation_config);
	inworld::optional_TextGenerationConfig optionalConfig = inworld::optional_TextGenerationConfig(text_generation_config);
	Out.text_generation_config(&optionalConfig);
#endif
}

void Convert(const TArray<FInworldLLMMessage>& In, inworld::Messages& Out)
{
#if defined(INWORLD_IMPLEMENTATION)
	for (const FInworldLLMMessage& Message : In)
	{
		inworld::Message message;
		switch (Message.Role)
		{
			case EInworldLLMMessageRole::USER:
				message.role("user");
				break;
			case EInworldLLMMessageRole::ASSISTANT:
				message.role("assistant");
				break;
			case EInworldLLMMessageRole::TOOL:
				message.role("tool");
				break;
			case EInworldLLMMessageRole::SYSTEM:
				message.role("system");
				break;
			case EInworldLLMMessageRole::DEVELOPER:
				message.role("developer");
				break;
		}
		message.SetTextContent(TCHAR_TO_UTF8(*Message.Content));
		Out.push_back(message);
	}
#endif
}

}	 // namespace inworld
