/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */
#include "GraphEditor/InworldGraphAssetEditor/EdNode_InworldGraphEdge.h"
#include "GraphEditor/InworldGraphAssetEditor/EdNode_InworldGraphNode.h"
#include "GraphEditor/InworldGraphAssetEditor/EdGraph_InworldGraph.h"
#include "Graph/Assets/InworldEdgeAsset.h"
#include "Graph/InworldGraphRuntimeData.h"
#include "Kismet2/KismetEditorUtilities.h"
#include "InworldRuntimeUtils.h"

#define LOCTEXT_NAMESPACE "EdNode_InworldGraphEdge"

UEdNode_InworldGraphEdge::UEdNode_InworldGraphEdge()
{
	bCanRenameNode = true;
}

void UEdNode_InworldGraphEdge::SetEdge(UInworldEdgeAsset* Edge)
{
	InworldGraphEdge = Edge;
}

void UEdNode_InworldGraphEdge::AllocateDefaultPins()
{
	UEdGraphPin* Inputs = CreatePin(EGPD_Input, TEXT("Edge"), FName(), TEXT("InEdge"));
	Inputs->bHidden = true;
	UEdGraphPin* Outputs = CreatePin(EGPD_Output, TEXT("Edge"), FName(), TEXT("OutEdge"));
	Outputs->bHidden = true;
}

FText UEdNode_InworldGraphEdge::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	if (InworldGraphEdge)
	{
		return InworldGraphEdge->GetNodeTitle();
	}
	return FText();
}

void UEdNode_InworldGraphEdge::PinConnectionListChanged(UEdGraphPin* Pin)
{
	if (Pin->LinkedTo.Num() == 0)
	{
		// transitions must always have an input and output connection
		Modify();

		// our parent graph will have our graph in SubGraphs so needs to be modified to record that.
		if (UEdGraph* ParentGraph = GetGraph())
		{
			ParentGraph->Modify();
		}

		DestroyNode();
	}
}

void UEdNode_InworldGraphEdge::PrepareForCopying()
{
	InworldGraphEdge->Rename(nullptr, this, REN_DontCreateRedirectors | REN_DoNotDirty);
	if (InworldGraphEdge->RuntimeEdge)
	{
		InworldGraphEdge->SerializedEdge = FInworldRuntimeUtils::SerializeInstance(InworldGraphEdge->RuntimeEdge);
	}
}

bool UEdNode_InworldGraphEdge::CanJumpToDefinition() const
{
	return (InworldGraphEdge != nullptr && InworldGraphEdge->GetClass() != nullptr);
}

void UEdNode_InworldGraphEdge::JumpToDefinition() const
{
	if (IsValid(InworldGraphEdge) && IsValid(InworldGraphEdge->RuntimeEdge))
	{
		if (UObject* HyperlinkTarget = InworldGraphEdge->RuntimeEdge->GetClass())
		{
			FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(HyperlinkTarget);
		}
	}
}

UEdGraphPin* UEdNode_InworldGraphEdge::GetStartPin() const
{
	if (Pins[0]->LinkedTo.Num() > 0)
	{
		return Pins[0]->LinkedTo[0];
	}
	return nullptr;
}

UEdGraphPin* UEdNode_InworldGraphEdge::GetEndPin() const
{
	if (Pins[1]->LinkedTo.Num() > 0)
	{
		return Pins[1]->LinkedTo[0];
	}
	return nullptr;
}

void UEdNode_InworldGraphEdge::CreateConnections(UEdNode_InworldGraphNode* Start, UEdNode_InworldGraphNode* End)
{
	Pins[0]->Modify();
	Pins[0]->LinkedTo.Empty();

	Start->GetOutputPin()->Modify();
	Pins[0]->MakeLinkTo(Start->GetOutputPin());

	// This to next
	Pins[1]->Modify();
	Pins[1]->LinkedTo.Empty();

	End->GetInputPin()->Modify();
	Pins[1]->MakeLinkTo(End->GetInputPin());
}

UEdNode_InworldGraphNode* UEdNode_InworldGraphEdge::GetStartNode()
{
	UEdGraphPin* StartPin = GetStartPin();
	return StartPin ? Cast<UEdNode_InworldGraphNode>(StartPin->GetOwningNode()) : nullptr;
}

UEdNode_InworldGraphNode* UEdNode_InworldGraphEdge::GetEndNode()
{
	UEdGraphPin* EndPin = GetEndPin();
	return EndPin ? Cast<UEdNode_InworldGraphNode>(EndPin->GetOwningNode()) : nullptr;
}

void UEdNode_InworldGraphEdge::SetRequired(bool IsRequired)
{
	if (IsValid(InworldGraphEdge))
	{
		InworldGraphEdge->SetRequired(IsRequired);
	}
}

void UEdNode_InworldGraphEdge::SetEdgeType(UClass* InEdgeType)
{
	if (IsValid(InworldGraphEdge))
	{
		InworldGraphEdge->SetEdgeType(InEdgeType);
		if (UEdGraph* EdGraph = GetGraph())
		{
			EdGraph->Modify();
		}
	}
}

#undef LOCTEXT_NAMESPACE
