#pragma once

#include "CoreMinimal.h"
#include "LevelSequence.h"
#include "LevelSequenceActor.h"
#include "Components/TimelineComponent.h"
#include "PortaSequenceFSMActor.generated.h"

class APortaStateTarget;

USTRUCT()
struct PORTAINTERFACE_API FPortaFSMTransition
{
	GENERATED_BODY()

	FPortaFSMTransition() = default;

	FPortaFSMTransition(ULevelSequence* Sequence, bool Reverse) : Sequence(Sequence), Reverse(Reverse) {}

	UPROPERTY()
	ULevelSequence* Sequence = nullptr;

	UPROPERTY()
	bool Reverse;
};

UCLASS()
class PORTAINTERFACE_API UPortaFSMState : public UObject
{
	GENERATED_BODY()
public:
	UPROPERTY(EditAnywhere, Category = "Porta")
	FString Name;

	UPROPERTY(EditAnywhere, Category = "Porta")
	TMap<FString, FPortaFSMTransition> Transitions;

	UPROPERTY(Transient)
	APortaStateTarget* Target;
};

UCLASS()
class PORTAINTERFACE_API APortaSequenceFSMActor : public AActor
{
	GENERATED_BODY()
public:
	APortaSequenceFSMActor();

	virtual void BeginPlay() override;

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void GotoState(const FString& State);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void GetStates(TArray<FString>& Results);

	void AddStateTarget(APortaStateTarget* Target);

	UPROPERTY(EditAnywhere, Category = "Porta")
	UCurveFloat* TargetsCurve;

	UPROPERTY(EditAnywhere, Category = "Porta")
	FString CurrentState;

	UPROPERTY(EditAnywhere, Category = "Porta")
	FString SequenceFolder;

	UPROPERTY(EditAnywhere, Category = "Porta")
	TMap<FString, UPortaFSMState*> States;

	UPROPERTY(EditAnywhere, Category = "Porta")
	AActor* ActorToMoveToTargets;

	UPROPERTY()
	UTimelineComponent* TargetsTimeline;

private:
	UPortaFSMState* FindOrCreateState(const FString& Key);
	UFUNCTION()
	void TimelineUpdate(float Update);

	UPROPERTY(Transient)
	ALevelSequenceActor* PlayerActor;

	FTransform StartTransform;
	FTransform EndTransform;
};
