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

#include "Engine/World.h"
#include "Graph/Assets/InworldGraphAsset.h"

FInworldGraphComponentBeginPlay UInworldGraphComponent::OnInworldGraphComponentBeginPlay;
FInworldGraphComponentEndPlay UInworldGraphComponent::OnInworldGraphComponentEndPlay;

UInworldGraphComponent::UInworldGraphComponent(const FObjectInitializer& ObjectInitializer)
{
	PrimaryComponentTick.bCanEverTick = false;
}

void UInworldGraphComponent::BeginPlay()
{
	Super::BeginPlay();

	OnInworldGraphComponentBeginPlay.Broadcast(this);

	if (bCreateGraphOnBeginPlay)
	{
		CreateGraph();
	}
}

void UInworldGraphComponent::EndPlay(EEndPlayReason::Type Reason)
{
	OnInworldGraphComponentEndPlay.Broadcast(this);

	Super::EndPlay(Reason);
}

void UInworldGraphComponent::CreateGraph()
{
	if (IsValid(GraphAsset))
	{
		GraphAsset->GetGraphInstance(FOnGraphCompiledNative::CreateWeakLambda(this,
			[this](UInworldGraph* CompiledGraph, bool bSuccess)
			{
				Graph = CompiledGraph;
				OnGraphCompiled(CompiledGraph, bSuccess);
				OnInworldGraphCompiled.Broadcast(this, bSuccess);
				OnInworldGraphCompiledNative.Broadcast(this, bSuccess);
			}));
	}
	else
	{
		UE_LOG(LogInworldGraph, Error, TEXT("UInworldGraphComponent::CreateGraph - GraphAsset is invalid"));
	}
}

void UInworldGraphComponent::OnGraphCompiled(UInworldGraph* CompiledGraph, bool bSuccess)
{
}

void UInworldGraphComponent::OnGraphResult_Implementation(
	const FString& ExecutionId, const FString& NodeId, const FInworldDataHandle& DataHandle)
{
}

FString UInworldGraphComponent::ExecuteGraph(
	const FInworldDataHandle& InputData, const TMap<FName, FInworldDataHandle>& RuntimeData)
{
	if (IsValid(Graph))
	{
		if (Graph->IsCompiled())
		{
			return Graph->Execute(this, InputData, RuntimeData,
				FOnGraphResultNative::CreateWeakLambda(this,
					[this](const FString& ExecutionId, const FString& NodeId, const FInworldDataHandle& Data)
					{
						OnGraphResult(ExecutionId, NodeId, Data);
						OnInworldGraphResult.Broadcast(this, ExecutionId, NodeId, Data);
						OnInworldGraphResultNative.Broadcast(this, ExecutionId, NodeId, Data);
					}),
				FOnGraphStatusNative::CreateWeakLambda(this,
					[this](const FString& ExecutionId, EInworldGraphExecutionStatus Status)
					{
						OnInworldGraphExecutionStatus.Broadcast(this, ExecutionId, Status);
						OnInworldGraphExecutionStatusNative.Broadcast(this, ExecutionId, Status);
					}));
		}
		else
		{
			UE_LOG(LogInworldGraph, Error, TEXT("UInworldGraphComponent::ExecuteGraph - Graph is not compiled"));
		}
	}
	else
	{
		UE_LOG(LogInworldGraph, Error, TEXT("UInworldGraphComponent::ExecuteGraph - Graph is invalid"));
	}
	return {};
}
