// Project Lab - NHTV Igad

#pragma once

#include "DealDamageProxy.h"
#include "AbilityEventGroup.generated.h"

UENUM(BlueprintType)
enum class EAbilityEventGroupProgressionType : uint8
{
	// Continues when the duration of the group has expired
	Continue,
	// Loops until the ability itself decides to continue, or is activated again
	Loop
};


UCLASS()
class UNREALPROJECT_API AAbilityEventGroup : public ADealDamageProxy
{
	GENERATED_BODY()

public:
	AAbilityEventGroup();

	virtual void BeginPlay() override final;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason);
	virtual void Tick(float DeltaSeconds) override final;

	// Used to construct an ability group sequence from an array of ability groups
	static AAbilityEventGroup* SpawnSequence(class ANetworkCharacter* character, class UAbilityInfo* abilityInfo, class AAbilityState* abilityState, TArray<TSubclassOf<class AAbilityEventGroup>> groups);

	// Try to interrupt this group chain if it's a channelEvent
	void Interrupt();

	// Changes the current group to execute this group now
	void TransitionTo(class AAbilityEventGroup* newGroup);

	// Try to continue this group if it's progression type is not duration bound
	UFUNCTION(BlueprintCallable, Category = "Ability")
	void NextGroup();

	// Value from 0 to 1 representing the life cycle of this event, loops back to 0 if the event is looping after the life exceeded the duration set in the group
	UFUNCTION(BlueprintCallable, Category = "Ability Group")
	float GetLifetimeRate() const;
	UFUNCTION(BlueprintCallable, Category = "Ability Group")
	float GetLifetime() const;

	UFUNCTION(BlueprintCallable, Category = "Ability")
	class ANetworkCharacter* GetTarget();

	UPROPERTY(BlueprintReadOnly, Category = "Ability Group")
	class AAbilityState* abilityState;
	UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Ability Group")
	float duration;
	UPROPERTY(EditDefaultsOnly, Category = "Ability Group")
	bool channelEvent;
	UPROPERTY(EditDefaultsOnly, Category = "Ability Group")
	bool stunWhileChannel;
	UPROPERTY(EditDefaultsOnly, Category = "Ability Group")
	bool allowRotateWhileChannel;

	// Setting this to true makes the ability 
	UPROPERTY(EditDefaultsOnly, Category = "Ability Group")
	EAbilityEventGroupProgressionType progressionType;

	// Called when the group's duration has expired or NextGroup is called
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnAbilityEventGroupEnded, class UAbilityInfo*, ability, class AAbilityEventGroup*, current, class AAbilityEventGroup*, next);
	FOnAbilityEventGroupEnded onAbilityEventGroupEnded;

private:
	UFUNCTION()
	void m_OnCharacterDestroyed();
	void m_MoveToNextGroup();
	void m_SendEndEvent(AAbilityEventGroup* next = nullptr);

	float m_life;

	UPROPERTY()
	TArray<TSubclassOf<AAbilityEventGroup>> m_nextGroups;
	
	bool m_hasBeenDestroyed;
	bool m_endEventSend;
	bool m_continue;
};
