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

#include "CoreMinimal.h"
#include "Graph/InworldEdge.h"
#include "InworldNodeAsset.h"

#include "InworldEdgeAsset.generated.h"

class UInworldGraphAsset;

/**
 * @class UInworldEdgeAsset
 * @brief Asset representation of a graph edge for editor and serialization purposes.
 *
 * This class serves as the asset version of an Inworld graph edge, containing
 * all the data necessary to represent, serialize, and manage connections between
 * nodes within the graph editor and runtime system. It maintains references to
 * connected nodes and manages the creation of runtime edge instances.
 */
UCLASS(Blueprintable)
class INWORLDRUNTIME_API UInworldEdgeAsset : public UObject
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the edge asset.
	 *
	 * Initializes the edge asset with default settings for graph editor and runtime use.
	 */
	UInworldEdgeAsset();

	/**
	 * @brief Destructor for the edge asset.
	 *
	 * Performs cleanup of edge asset resources and references.
	 */
	~UInworldEdgeAsset();

	/** The source node asset that this edge originates from */
	UPROPERTY(Meta = (ToolTip = "The source node asset that this edge originates from"))
	TObjectPtr<UInworldNodeAsset> StartNode;

	/** The destination node asset that this edge connects to */
	UPROPERTY(Meta = (ToolTip = "The destination node asset that this edge connects to"))
	TObjectPtr<UInworldNodeAsset> EndNode;

	/** Index of the output pin on the start node for this connection */
	UPROPERTY(Meta = (ToolTip = "Index of the output pin on the start node for this connection"))
	int32 StartPinIndex = 0;

	/** Index of the input pin on the end node for this connection */
	UPROPERTY(Meta = (ToolTip = "Index of the input pin on the end node for this connection"))
	int32 EndPinIndex;

#if WITH_EDITORONLY_DATA
	/** Whether to display the edge title in the graph editor */
	UPROPERTY(Meta = (ToolTip = "Whether to display the edge title in the graph editor"))
	bool bShouldDrawTitle = false;

	/** The display title for this edge in the graph editor */
	UPROPERTY(Meta = (ToolTip = "The display title for this edge in the graph editor"))
	FText EdgeTitle{};

	/** The color used to render this edge in the graph editor */
	UPROPERTY(Meta = (ToolTip = "The color used to render this edge in the graph editor"))
	FLinearColor EdgeColor = FLinearColor(0.9f, 0.9f, 0.9f, 1.0f);

	/** Whether this edge has been properly initialized in the editor */
	UPROPERTY(Meta = (ToolTip = "Whether this edge has been properly initialized in the editor"))
	bool IsEdgeInitialized{false};
#endif

	/** The runtime class type that this edge asset will instantiate */
	UPROPERTY(Meta = (ToolTip = "The runtime class type that this edge asset will instantiate"))
	TSubclassOf<UInworldEdge> EdgeType;

	/** The actual runtime edge instance created from this asset */
	UPROPERTY(VisibleAnywhere, Instanced, BlueprintReadOnly, Category = "Inworld",
		Meta = (ToolTip = "The actual runtime edge instance created from this asset"))
	TObjectPtr<UInworldEdge> RuntimeEdge;

	/** Serialized data of the runtime edge for persistence and loading */
	UPROPERTY(Meta = (ToolTip = "Serialized data of the runtime edge for persistence and loading"))
	FString SerializedEdge;

	/**
	 * @brief Retrieves the name of the start node for this edge.
	 *
	 * This function returns the name of the source node that this edge originates from.
	 * Used for identifying connections and debugging purposes.
	 *
	 * @return The name of the start node as a string
	 */
	FString GetStartNodeName() const;

	/**
	 * @brief Retrieves the name of the end node for this edge.
	 *
	 * This function returns the name of the destination node that this edge connects to.
	 * Used for identifying connections and debugging purposes.
	 *
	 * @return The name of the end node as a string
	 */
	FString GetEndNodeName() const;

#if WITH_EDITOR
	/**
	 * @brief Called when a property is changed in the editor.
	 *
	 * This override handles property change notifications and performs any necessary
	 * updates when edge properties are modified in the editor interface.
	 *
	 * @param PropertyChangedEvent Event information about the property that changed
	 */
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;

	/**
	 * @brief Retrieves the display title of this edge for UI purposes.
	 *
	 * This function returns the edge's title as formatted text suitable for
	 * display in the graph editor and other user interfaces.
	 *
	 * @return The formatted edge title as FText
	 */
	FText GetNodeTitle() const;

	/**
	 * @brief Sets a new title for this edge in the editor.
	 *
	 * This function updates the edge's display title to the provided text.
	 * The change is reflected in the graph editor interface.
	 *
	 * @param NewTitle The new title text to assign to this edge
	 */
	void SetNodeTitle(const FText& NewTitle);

	/**
	 * @brief Retrieves the color used to render this edge in the editor.
	 *
	 * This function returns the current color settings for edge visualization
	 * in the graph editor, allowing for customized edge appearance.
	 *
	 * @return The edge's display color as FLinearColor
	 */
	FLinearColor GetEdgeColor();

	/**
	 * @brief Creates the runtime edge instance from this asset.
	 *
	 * This function instantiates the actual runtime edge based on this asset's
	 * configuration, preparing it for graph execution. Used during graph compilation.
	 *
	 * @param Outer Optional graph asset that will own the created runtime edge
	 */
	void CreateRuntimeEdge(UInworldGraphAsset* Outer = nullptr);

	/**
	 * @brief Checks if this edge is required for graph execution.
	 *
	 * This function returns whether this edge is marked as required, meaning
	 * the graph cannot execute properly without this connection.
	 *
	 * @return True if the edge is required, false otherwise
	 */
	bool GetIsRequired() const;

	/**
	 * @brief Sets the required status of this edge.
	 *
	 * This function marks the edge as required or optional for graph execution.
	 * Required edges must be present for successful graph compilation and execution.
	 *
	 * @param IsRequired True to mark as required, false for optional
	 */
	void SetRequired(bool IsRequired);

	/**
	 * @brief Sets the runtime edge type class for this asset.
	 *
	 * This function configures which edge class type will be instantiated
	 * when creating the runtime edge from this asset.
	 *
	 * @param InEdgeType The class type to use for runtime edge creation
	 */
	void SetEdgeType(UClass* InEdgeType);
#endif
};
