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

#include "Graph/Assets/InworldGraphAsset.h"
#include "Graph/Edges/InworldEdge_SafetyResult.h"
#include "Graph/InworldGraph.h"

UInworldEdgeAsset::UInworldEdgeAsset()
{
	EdgeType = UInworldEdge::StaticClass();
}

UInworldEdgeAsset::~UInworldEdgeAsset()
{
}

FString UInworldEdgeAsset::GetStartNodeName() const
{
	if (IsValid(StartNode) && IsValid(StartNode->RuntimeNode))
	{
		return StartNode->RuntimeNode->GetNodeName();
	}
	return TEXT("StartNode_NotValid");
}

FString UInworldEdgeAsset::GetEndNodeName() const
{
	if (IsValid(EndNode) && IsValid(EndNode->RuntimeNode))
	{
		return EndNode->RuntimeNode->GetNodeName();
	}
	return TEXT("EndNode_NotValid");
}

#if WITH_EDITOR

void UInworldEdgeAsset::CreateRuntimeEdge(UInworldGraphAsset* Outer)
{
	if (Outer == nullptr)
	{
		Outer = Cast<UInworldGraphAsset>(GetOuter());
	}

	// reset edge asset
	EdgeTitle = FText::FromString("");
	bShouldDrawTitle = false;
	EdgeColor = FLinearColor(0.9f, 0.9f, 0.9f, 0.9f);

	// create runtime edge
	if (EdgeType && Outer && Outer->RuntimeGraph)
	{
		RuntimeEdge = NewObject<UInworldEdge>(Outer->RuntimeGraph, EdgeType);

		// SafetyEdge
		if (UInworldEdge_SafetyResult* SafetyEdge = Cast<UInworldEdge_SafetyResult>(RuntimeEdge))
		{
			EdgeTitle = FText::FromString(SafetyEdge->EdgeTitle);
			bShouldDrawTitle = true;
			EdgeColor = FLinearColor(0.0f, 1.0f, 0.0f, 0.9f);
		}
		// WithCondition
		else if (UInworldEdge_WithCondition* WithConditionEdge = Cast<UInworldEdge_WithCondition>(RuntimeEdge))
		{
			if (!WithConditionEdge->EdgeTitle.IsEmpty())
			{
				EdgeTitle = FText::FromString(WithConditionEdge->EdgeTitle);
				bShouldDrawTitle = true;
			}
		}
	}
}

bool UInworldEdgeAsset::GetIsRequired() const
{
	if (IsValid(RuntimeEdge))
	{
		return RuntimeEdge->IsRequired;
	}
	return true;
}
void UInworldEdgeAsset::SetRequired(bool IsRequired)
{
	if (IsValid(RuntimeEdge) && !IsEdgeInitialized)
	{
		RuntimeEdge->IsRequired = IsRequired;
		IsEdgeInitialized = true;
	}
}

void UInworldEdgeAsset::SetEdgeType(UClass* InEdgeType)
{
	bool isRequiredState = (RuntimeEdge && RuntimeEdge->IsRequired);
	EdgeType = InEdgeType;
	CreateRuntimeEdge();
	RuntimeEdge->IsRequired = isRequiredState;
}

FText UInworldEdgeAsset::GetNodeTitle() const
{
	return EdgeTitle;
}

FLinearColor UInworldEdgeAsset::GetEdgeColor()
{
	return EdgeColor;
}

void UInworldEdgeAsset::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);
	const FName PropertyName{(PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None};
	if (PropertyName == GET_MEMBER_NAME_CHECKED(UInworldEdgeAsset, EdgeType) && EdgeType)
	{
		CreateRuntimeEdge();
	}
	else if (PropertyName == GET_MEMBER_NAME_CHECKED(UInworldEdgeAsset, RuntimeEdge))
	{
		if (UInworldEdge_WithCondition* RuntimeConditionEdge = Cast<UInworldEdge_WithCondition>(RuntimeEdge))
		{
			bShouldDrawTitle = !RuntimeConditionEdge->EdgeTitle.IsEmpty();
			FString EdgeTitleStr = RuntimeConditionEdge->EdgeTitle;

			// SafetyEdge
			if (UInworldEdge_SafetyResult* SafetyEdge = Cast<UInworldEdge_SafetyResult>(RuntimeEdge))
			{
				EdgeColor =
					(SafetyEdge->bRequireSafe) ? FLinearColor(0.0f, 1.0f, 0.0f, 0.9f) : FLinearColor(1.0f, 0.0f, 0.0f, 0.9f);
				if (!SafetyEdge->bRequireSafe)
				{
					EdgeTitleStr = FString::Printf(TEXT("Not %s"), *EdgeTitleStr);
				}
			}
			// ConditionalEdge
			else
			{
				if (RuntimeConditionEdge->bNegateCondition)
				{
					EdgeTitleStr = FString::Printf(TEXT("Not %s"), *EdgeTitleStr);
				}
			}
			EdgeTitle = FText::FromString(EdgeTitleStr);
		}
	}
}

void UInworldEdgeAsset::SetNodeTitle(const FText& NewTitle)
{
	EdgeTitle = NewTitle;
}
#endif	  // #if WITH_EDITOR
