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

#pragma once

#include "CoreMinimal.h"
#include "Graph/Edges/InworldEdge_WithCondition.h"
#include "Graph/InworldData.h"

#include "InworldEdge_IsDataType.generated.h"

/**
 * @brief Represents an edge with a specific data type as its evaluation condition.
 *
 * This class allows for the creation and evaluation of edges in a graph with a condition that
 * checks if the input data matches a specified data type. It extends UInworldEdge_WithCondition
 * to provide additional functionality related to data type checking. This edge can be created and
 * configured at runtime or within the editor. Users can override its behavior by modifying the
 * MeetsCondition method in derived classes.
 */
UCLASS(Blueprintable, BlueprintType)
class INWORLDRUNTIME_API UInworldEdge_IsDataType : public UInworldEdge_WithCondition
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the data type checking edge.
	 *
	 * Initializes the edge with default settings for data type-based flow control.
	 * Sets the edge title to "Is Type" to indicate its data type evaluation purpose.
	 */
	UInworldEdge_IsDataType()
	{
		EdgeTitle = "Is Type";
	}
	/**
	 * @brief Native utility function. Creates a new data type checking edge instance
	 * @param Outer The UObject that will own this edge
	 * @param Source The source node name
	 * @param Destination The destination node name
	 * @param IsRequired Whether this edge is required for graph execution
	 * @param IsLoopEdge Whether this edge creates a loop in the graph
	 * @param DataType The data type to accept when evaluating this edge
	 * @return Newly created data type checking edge
	 */
	static UInworldEdge_IsDataType* CreateNative(UObject* Outer, const FString& Source, const FString& Destination, bool IsRequired,
		bool IsLoopEdge, UScriptStruct* DataType)
	{
		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_IsDataType* NewNode = NewObject<UInworldEdge_IsDataType>(Outer, FName(ObjectName));
		NewNode->Source = Source;
		NewNode->Destination = Destination;
		NewNode->IsRequired = IsRequired;
		NewNode->IsLoopEdge = IsLoopEdge;
		NewNode->DataType = DataType;
		return NewNode;
	}

protected:
	/**
	 * @brief Specifies the data type associated with this edge.
	 *
	 * The data type defines the type of input data this edge expects to process when determining
	 * whether it meets the specified condition. This property is editable in the editor and can
	 * also be read or written to within Blueprints.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld",
		Meta = (ToolTip = "The data type that this edge expects to process when evaluating its condition"))
	UScriptStruct* DataType{};

	UFUNCTION()
	bool MeetsCondition_Default(const UInworldProcessContext* ProcessContext, const FInworldDataHandle& Input) const;

private:
	friend class UInworldEdgeAsset;
};
