// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"

#include "Data/ComboActionGraphDataTypes.h"
#include "Nodes/ComboActionGraphNode.h"
#include "UObject/Object.h"

#include "ComboActionContext.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FComboActionContextUpdatedFromBlueprint, class UComboActionContext *, Context);


/**
 * Dialogue Context.
 * 
 * Contains information needed to successfully start Dialogue.
 * Also helps tracking Dialogue Specific data. Is recycled for whole Dialogue Graph.
 * 
 * In Dialogue Manager Component is used as Transient object, which is nullified once Dialogue ends and is never saved.
 */
UCLASS()
class COMBOINPUT_API UComboActionContext : public UObject
{
	GENERATED_BODY()

public:

	///**
	// * Active Dialogue Participant Interface reference.
	// * 
	// * This is the Participant who is Active right now.
	// * ❔ Lead Node sets this value to Dialogue Participant.
	// * ❔ Answer Node sets this value to Player Participant.
	// * ❗ Might be invalid
	// */
	//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
	//	TScriptInterface<IComboActionParticipantInterface> ActionParticipant;
	
	///**
	// * Player Dialogue Participant Interface reference.
	// * 
	// * This is the Participant who represent the Player.
	// * ❗ Might be invalid
	// */
	//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
	//	TScriptInterface<class IComboActionParticipantInterface> PlayerDialogueParticipant;

	//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
	//	TScriptInterface<class IComboActionParticipantInterface> DialogueParticipant;

	//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
	//	TArray<TScriptInterface<class IComboActionParticipantInterface>> DialogueParticipants;
	
	/**
	 * Pointer to the Node which is currently active.
	 * ❗ Might be null
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
		class UComboActionGraphNode *ActiveNode = nullptr;
	
	/**
	 * List of Nodes that can be accessed from Active Node.
	 * Already filtered to contain only those that can be triggered.
	 * 
	 * ❔ Filter is done by 'CanStartNode', which can have its own logic and can be driven by Decorators as well.
	 * ❗ Might be empty
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
		TArray<class UComboActionGraphNode*> AllowedChildNodes;
	
	/**
	 * Index of currently used Dialogue Row Data row.
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
		int32 ActiveDialogueRowDataIndex = 0;
	
	/**
	 * Contains mapped list of Traversed Nodes by GUIDs.
	 * Each time Dialogue is updated, like node is selected or starts itself, this Path is updated.
	 * Updates Participant once Dialogue is done.
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action", meta=(NoResetToDefault))
		TMap<FGuid, int32> TraversedPath;

public:

	UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action|Debug")
		virtual bool IsValid() const;

	//TScriptInterface<class IComboActionParticipantInterface> GetDialoguePlayerParticipant() const { return this->PlayerDialogueParticipant; }
	//TScriptInterface<class IComboActionParticipantInterface> GetDialogueParticipant() const { return this->DialogueParticipant; }
	//TArray<TScriptInterface<class IComboActionParticipantInterface>> GetDialogueParticipants() const { return this->DialogueParticipants; }

	/**
	 * Returns the Active Node object.
	 * ❗ Might be null
	 * 
	 * @return Active Node if any specified
	 */
	class UComboActionGraphNode *GetActiveNode() const { return this->ActiveNode; }

	/**
	 * Returns lsit of Children Nodes from Active Node.
	 * ❗ Might be empty
	 * 
	 * @return List of allowed Children Nodes 
	 */
	TArray<class UComboActionGraphNode*> GetChildrenNodes() const { return this->AllowedChildNodes; }
	///**
	// *Returns the Active Dialogue Row Data Index.
	// * 
	// * @return Active Row Index 
	// */
	//int32 GetActiveDialogueRowDataIndex() const { return this->ActiveDialogueRowDataIndex; }
	/**
	 * Returns the map of nodes traversed during this dialogue instance.
	 * 
	 * @return The map of nodes traversed during this dialogue instance.
	 */
	TMap<FGuid, int32> GetTraversedPath() const { return TraversedPath; }
	
	virtual void SetComboActionContext(class UComboActionGraphNode *NewActiveNode, TArray<class UComboActionGraphNode*> NewAllowedChildNodes);
	//virtual void UpdateDialogueParticipant(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
	//virtual void UpdateActiveDialogueNode(class UComboActionGraphNode *NewActiveNode);
	//virtual void UpdateAllowedChildrenNodes(const TArray<class UComboActionGraphNode*> &NewNodes);
	//virtual void UpdateActiveDialogueRowDataIndex(int32 NewIndex);
	//void UpdateDialoguePlayerParticipant(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
	//void UpdateActiveDialogueParticipant(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
	//void AddTraversedNode(const class UComboActionGraphNode* TraversedNode);

	//virtual bool AddDialogueParticipants(const TArray<TScriptInterface<class IComboActionParticipantInterface>> &NewParticipants);
	//virtual bool AddDialogueParticipant(const TScriptInterface<class IComboActionParticipantInterface> &NewParticipant);
	//virtual bool RemoveDialogueParticipants(const TArray<TScriptInterface<class IComboActionParticipantInterface>> &NewParticipants);
	//virtual bool RemoveDialogueParticipant(const TScriptInterface<class IComboActionParticipantInterface> &NewParticipant);
	//virtual void ClearDialogueParticipants();
	
	/**
	 * Sets the dialogue context.
	 *
	 * @param NewParticipant The new dialogue participant.
	 * @param NewActiveNode The new active dialogue node.
	 * @param NewAllowedChildNodes The new allowed child dialogue nodes.
	 */
	UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="SetDialogueContext"))
		virtual void SetComboActionContextBP(class UComboActionGraphNode *NewActiveNode, TArray<class UComboActionGraphNode*> NewAllowedChildNodes);

	///**
	// * Updates Dialogue Participant.
	// *
	// * @param NewParticipant - new Dialogue Participant.
	// * ❗ Must implement IComboActionParticipantInterface.
	// */
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateDialogueParticipant"))
	//	virtual void UpdateDialogueParticipantBP(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
	/**
	 * Updates Active Dialogue Node in Context.
	 * 
	 * @param NewActiveNode - New Active Dialogue Node to update to.
	 * ❗ Must not be Null
	 */
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateActiveDialogueNode"))
	//	virtual void UpdateActiveDialogueNodeBP(class UComboActionGraphNode *NewActiveNode);
	/**
	 * Updates the active dialogue row Data Index.
	 * 
	 * @param NewIndex - The new active dialogue data row Index.
	 */
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateActiveDialogueRowDataIndex"))
	//	virtual void UpdateActiveDialogueRowDataIndexBP(int32 NewIndex);
	///**
	// * Updates Dialogue Player Participant.
	// *
	// * @param NewParticipant - new Dialogue Player Participant.
	// * ❗ Must implement IMounteaDialogueParticipantInterface.
	// */
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateDialoguePlayerParticipant"))
	//	void UpdateDialoguePlayerParticipantBP(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
	///**
	// * Updates Dialogue Active Participant.
	// *
	// * @param NewParticipant - new Dialogue Active Participant.
	// * ❗ Must implement IMounteaDialogueParticipantInterface.
	// */
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateActiveDialogueParticipant"))
	//	void UpdateActiveDialogueParticipantBP(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);

	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="AddDialogueParticipant"))
	//	virtual bool AddDialogueParticipantBP(const TScriptInterface<class IComboActionParticipantInterface>& NewParticipant);
	//
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="RemoveDialogueParticipant"))
	//	virtual bool RemoveDialogueParticipantBP(const TScriptInterface<class IComboActionParticipantInterface>& NewParticipant);

	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="AddDialogueParticipants"))
	//	virtual bool AddDialogueParticipantsBP(const TArray<TScriptInterface<class IComboActionParticipantInterface>>& NewParticipants);
	//
	//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="RemoveDialogueParticipants"))
	//	virtual bool RemoveDialogueParticipantsBP(const TArray<TScriptInterface<class IComboActionParticipantInterface>>& NewParticipants);
	
	FComboActionContextUpdatedFromBlueprint ComboActionContextUpdatedFromBlueprint;
};
