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

#pragma once

#include "Engine/DataAsset.h"
#include "InworldTextEmbedderTypes.h"

#include "InworldTextEmbedding.generated.h"

/**
 * @struct FInworldTextEmbedding
 * @brief Structure representing a text string and its corresponding embedding vector.
 *
 * This structure encapsulates a piece of text along with its normalized form and
 * the numerical embedding vector that represents its semantic meaning for similarity comparisons.
 */
USTRUCT(BlueprintType)
struct INWORLDRUNTIME_API FInworldTextEmbedding
{
	GENERATED_BODY()

	/** The original text string that was embedded */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inworld|Text Embedding")
	FString Text;

	/** The normalized version of the text used for embedding generation */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inworld|Text Embedding")
	FString NormalizedText;

	/** The numerical embedding vector representing the semantic meaning of the text */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inworld|Text Embedding")
	TArray<float> Values;
};

/**
 * @struct FInworldTextEmbeddings
 * @brief Deprecated structure for text embeddings (use FInworldTextEmbedding instead).
 *
 * This structure is deprecated as of version 0.8. Use the individual FInworldTextEmbedding
 * struct instead for better control over embedding data and normalization.
 */
USTRUCT(BlueprintType, meta = (Deprecated = "0.8"))
struct INWORLDRUNTIME_API FInworldTextEmbeddings
{
	GENERATED_BODY()

	/** Array of text strings (deprecated - use FInworldTextEmbedding instead) */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inworld|Text Embedding")
	TArray<FString> Text;
};

/**
 * @class UInworldTextEmbeddingAsset
 * @brief Data asset for storing and managing text embeddings.
 *
 * This asset class provides functionality for storing collections of text embeddings,
 * generating embeddings from text data, and managing the embedding lifecycle within
 * the Unreal Engine editor and runtime environments.
 */
UCLASS(BlueprintType)
class INWORLDRUNTIME_API UInworldTextEmbeddingAsset : public UDataAsset
{
	GENERATED_BODY()

	friend class UInworldEditorTextEmbedder;

public:
	/** Array of text embeddings stored in this asset */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inworld")
	TArray<FInworldTextEmbedding> TextEmbeddings;

	/** Deprecated text embeddings structure (use TextEmbeddings instead) */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inworld",
		meta = (EditCondition = "false", DeprecatedProperty, DeprecationMessage = "Use Text Embeddings Instead!"))
	FInworldTextEmbeddings InworldTextEmbeddings;

#if WITH_EDITOR
	virtual void PostLoad() override;
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
	virtual void PreSave(FObjectPreSaveContext SaveContext) override;

	/**
	 * @brief Starts the embedding generation process for the asset's text data.
	 *
	 * This function initiates the process of generating embeddings for all text entries
	 * in the asset using the configured text embedder settings.
	 */
	void StartEmbeddingGeneration();

	/**
	 * @brief Generates embeddings with a completion callback.
	 *
	 * This function generates embeddings for the asset's text data and calls the provided
	 * callback function when the operation completes, indicating success or failure.
	 *
	 * @param OnComplete Callback function called when embedding generation completes
	 */
	void GenerateEmbeddingsWithCallback(TFunction<void(bool bSuccess)> OnComplete);

	/**
	 * @brief Retrieves all available text embedder configuration IDs.
	 *
	 * This static function returns a list of all available text embedder configuration
	 * identifiers that can be used for generating embeddings.
	 *
	 * @return Array of available configuration ID strings
	 */
	static TArray<FString> GetAvailableConfigIds();
#endif

#if WITH_EDITORONLY_DATA
	/** The currently selected configuration ID for embedding generation */
	UPROPERTY(EditAnywhere, Category = "Inworld")
	FString SelectedConfigId;

	/** Flag indicating whether embedding generation is currently in progress */
	UPROPERTY(Transient)
	bool bIsGeneratingEmbeddings = false;
#endif

private:
	/**
	 * @brief Retrieves the source text array for embedding generation.
	 * @return Array of source text strings to be embedded
	 */
	TArray<FString> GetSourceTextArray() const;

	/**
	 * @brief Clears all calculated embedding data and cached information.
	 */
	void ClearCalculatedData();

	/** Flag indicating whether calculated embedding data is available */
	UPROPERTY()
	bool bHasCalculatedData{false};

	/** Cache of the text array used for the last embedding generation */
	UPROPERTY()
	TArray<FString> CachedTextForLastEmbedding;

	/** Cache of the configuration ID used for the last embedding generation */
	UPROPERTY()
	FString CachedConfigIdForLastEmbedding;
};
