/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */
#include "Graph/InworldEdge.h"

#include "Dom/JsonObject.h"
#include "Engine/Engine.h"
#include "Graph/InworldGraph.h"
#include "InworldRuntimeSubsystem.h"
#include "InworldRuntimeUtils.h"
#include "Serialization/JsonSerializer.h"

THIRD_PARTY_INCLUDES_START
#include "InworldRuntimeLibrary/inworld.h"
THIRD_PARTY_INCLUDES_END

void UInworldEdge::InitializeEdge(const FString& InstanceData)
{
	FInworldRuntimeUtils::DeserializeInstance(this, InstanceData);
}

void UInworldEdge::DestroyEdge()
{
	bPendingDestroy = true;
	this->ConditionalBeginDestroy();
}

void UInworldEdge::BeginDestroy()
{
	if (bPendingDestroy)
	{
		const FString ConditionId = FString::Printf(TEXT("%s_to_%s"), *Source, *Destination).Replace(TEXT(" "), TEXT(""));
		UE_LOG(LogInworldGraph, Log, TEXT("UInworldEdge::BeginDestroy - %s"), *ConditionId);
	}
	Super::BeginDestroy();
}

UInworldEdge* UInworldEdge::CreateNative(
	UObject* Outer, const FString& Source, const FString& Destination, bool IsRequired, bool IsLoopEdge)
{
	const FString SourceFormated = Source.Replace(TEXT(" "), TEXT(""));
	const FString DestinationFormated = Destination.Replace(TEXT(" "), TEXT(""));
	const FString ObjectName = FString::Printf(TEXT("Edge_%s_to_%s"), *SourceFormated, *DestinationFormated);
	UInworldEdge* NewEdge = NewObject<UInworldEdge>(Outer, FName(ObjectName));
	NewEdge->Source = Source;
	NewEdge->Destination = Destination;
	NewEdge->IsRequired = IsRequired;
	NewEdge->IsLoopEdge = IsLoopEdge;

	return NewEdge;
}

TArray<FString> UInworldEdge::GetNodeNames() const
{
	if (UInworldGraph* Outer = Cast<UInworldGraph>(GetOuter()); Outer != nullptr)
	{
		return Outer->GetNodeNames();
	}
	return {};
}

EInworldRuntimeErrors UInworldEdge::GetJsonConfig(const TSharedRef<FJsonObject>& GraphJson)
{
	TSharedPtr<FJsonObject> EdgeObj = MakeShared<FJsonObject>();
	EdgeObj->SetStringField(TEXT("from_node"), Source);
	EdgeObj->SetStringField(TEXT("to_node"), Destination);
	EdgeObj->SetBoolField(TEXT("optional"), !IsRequired);
	EdgeObj->SetBoolField(TEXT("loop"), IsLoopEdge);

	TSharedPtr<FJsonObject> Main = GraphJson->GetObjectField(TEXT("main"));
	TArray<TSharedPtr<FJsonValue>> Edges = Main->GetArrayField(TEXT("edges"));
	Edges.Add(MakeShared<FJsonValueObject>(EdgeObj));
	Main->SetArrayField(TEXT("edges"), Edges);

	return EInworldRuntimeErrors::SUCCESS;
}
