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

#include "Graph/Nodes/InworldNode_TextProcessing.h"

#include "Graph/InworldData.h"
#include "Graph/InworldGraph.h"
#include "InworldBlueprintFunctionLibrary.h"

THIRD_PARTY_INCLUDES_START
#include "InworldRuntimeLibrary/inworld.h"
THIRD_PARTY_INCLUDES_END

UInworldNode_TextProcessing::UInworldNode_TextProcessing()
{
	NodeName = "Text Processing";
}

FInworldData_DataStream_String UInworldNode_TextProcessing::Process_Default(
	const UInworldProcessContext* ProcessContext, const FInworldData_DataStream_String& TextStream) const
{
	if (TextStream.InputStream.IsValid())
	{
		return Process_DataStream_String(ProcessContext, TextStream);
	}

	return FInworldData_DataStream_String::Error(TEXT("Invalid input stream."));
}

UInworldNode_GeneralTextProcessor::UInworldNode_GeneralTextProcessor()
{
	NodeName = "General Text Processor";
	bExecuteProcessInGameThread = false;
}

FInworldData_DataStream_String UInworldNode_GeneralTextProcessor::Process_DataStream_String(
	const UInworldProcessContext* ProcessContext, const FInworldData_DataStream_String& Input) const
{
	FInworldData_DataStream_String Output;
	Output.InputStream = Input.InputStream;

	if (bRemoveTextInBrackets)
	{
		inworld::StatusOr_TextInBracketsRemover status_or_text_in_brackets_remover =
			inworld::TextInBracketsRemover::Create(*Output.InputStream.Get());
		if (status_or_text_in_brackets_remover.ok())
		{
			inworld::TextInBracketsRemover text_in_brackets_remover{status_or_text_in_brackets_remover.value()};
			inworld::DataStream_String datastream_string{text_in_brackets_remover};
			Output.InputStream = MakeShared<inworld::InputStream_string>(datastream_string.stream());
		}
	}

	if (bRemoveSubstrings)
	{
		inworld::vector_string substrings = GetSubstringsToRemove(ProcessContext);

		inworld::StatusOr_SubstringRemover status_or_substring_remover =
			inworld::SubstringRemover::Create(*Output.InputStream.Get(), substrings);
		if (status_or_substring_remover.ok())
		{
			inworld::SubstringRemover substring_remover{status_or_substring_remover.value()};
			inworld::DataStream_String datastream_string{substring_remover};
			Output.InputStream = MakeShared<inworld::InputStream_string>(datastream_string.stream());
		}
	}

	if (bProcessAsSentenceStream)
	{
		inworld::StatusOr_SentenceStream status_or_sentence_stream = inworld::SentenceStream::Create(*Output.InputStream.Get());
		if (status_or_sentence_stream.ok())
		{
			inworld::SentenceStream sentence_stream{status_or_sentence_stream.value()};
			inworld::DataStream_String datastream_string{sentence_stream};
			Output.InputStream = MakeShared<inworld::InputStream_string>(datastream_string.stream());
		}
	}

	if (bRemoveEmojis)
	{
		inworld::StatusOr_EmojiRemover status_or_emoji_remover = inworld::EmojiRemover::Create(*Output.InputStream.Get());
		if (status_or_emoji_remover.ok())
		{
			inworld::EmojiRemover emoji_remover{status_or_emoji_remover.value()};
			inworld::DataStream_String datastream_string{emoji_remover};
			Output.InputStream = MakeShared<inworld::InputStream_string>(datastream_string.stream());
		}
	}
	return Output;
}

inworld::vector_string UInworldNode_GeneralTextProcessor::GetSubstringsToRemove(const UInworldProcessContext* ProcessContext) const
{
	inworld::vector_string substrings;
	for (const FString& Str : SubstringsToRemove)
	{
		substrings.push_back(TCHAR_TO_UTF8(*Str));
	}

	if (bRemovePlayerName)
	{
		if (FInworldPlayerProfile PlayerProfile; ProcessContext->GetRuntimeStruct(PlayerProfileRuntimeDataKey, PlayerProfile))
		{
			const FString PlayerNameStringToRemove = FString::Printf(TEXT("%s:"), *PlayerProfile.Name);
			substrings.push_back(TCHAR_TO_UTF8(*PlayerNameStringToRemove));
		}
	}
	return substrings;
}
