// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.

#pragma once

#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "OLSEnumLibrary.h"
#include "OLSLocomotionData.h"
#include "UObject/Object.h"
#include "OLSAnimationData.generated.h"

USTRUCT(BlueprintType)
struct FOLSTurnInPlaceAnimSet
{
	GENERATED_BODY()

public:

	FORCEINLINE class UAnimSequence* GetTurnInPlaceAnimationByDirection(const float direction) const;
	
public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "TurnInPlace Anim Set")
	TObjectPtr<class UAnimSequence> TurnInPlace_90_L = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "TurnInPlace Anim Set")
	TObjectPtr<class UAnimSequence> TurnInPlace_90_R = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "TurnInPlace Anim Set")
	TObjectPtr<class UAnimSequence> TurnInPlace_180_L = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "TurnInPlace Anim Set")
	TObjectPtr<class UAnimSequence> TurnInPlace_180_R = nullptr;
};

USTRUCT(BlueprintType)
struct FOLSAimAnimSet
{
	GENERATED_BODY()
	
public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Aim Anim Set")
	TObjectPtr<class UAnimSequence> AimPose = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Aim Anim Set")
	TObjectPtr<class UAimOffsetBlendSpace> IdleAimOffset = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Aim Anim Set")
	TObjectPtr<class UAimOffsetBlendSpace> RelaxedAimOffset = nullptr;
	
};

USTRUCT(BlueprintType)
struct FOLSIdleAnimSet
{
	GENERATED_BODY()
	
public:

	FORCEINLINE bool HasAnyIdleBreaks() const;
	FORCEINLINE class UAnimSequence* GetIdleAnimation(const bool isAiming) const;
	FORCEINLINE class UAnimSequence* GetRandomIdleBreakAnimation() const;
	
public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Idle Anim Set")
	TArray<class UAnimSequence*> IdleBreaks;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Idle Anim Set")
	TObjectPtr<class UAnimSequence> Idle = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Idle Anim Set")
	TObjectPtr<class UAnimSequence> IdleADS = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Idle Anim Set")
	TObjectPtr<class UAnimSequence> IdleEntry = nullptr;
};

USTRUCT(BlueprintType)
struct FOLSIdleAndTurnInPlaceAnimSet
{
	GENERATED_BODY()

public:

	FORCEINLINE class UAnimSequence* GetIdleEntryAnimation() const;
	FORCEINLINE class UAnimSequence* GetIdleAnimation(const bool isAiming) const;
	FORCEINLINE class UAnimSequence* GetRandomIdleBreakAnimation() const;
	FORCEINLINE class UAnimSequence* GetTurnInPlaceAnimation(const float direction) const;
	FORCEINLINE bool CanPlayIdleBreakAnimation() const;

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Idle and Turn In Place Anim Set")
	FOLSIdleAnimSet IdleAnimSet;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Idle and Turn In Place Anim Set")
	FOLSTurnInPlaceAnimSet TurnInPlaceAnimSet;
};

USTRUCT(BlueprintType)
struct FOLSMovementAnimSet
{
	GENERATED_BODY()

public:

	class UAnimSequence* GetMovementAnimationByCardinalDirection(const EOLSCardinalDirection& direction) const;

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Forward = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Backward = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Right = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Left = nullptr;
};

USTRUCT(BlueprintType)
struct FOLSMovementAnimSet_ForwardFacing
{
	GENERATED_BODY()

public:

	class UAnimSequence* GetBackwardLeftRightByAngle(const float angle) const;
	class UAnimSequence* GetMovementAnimationByAngle(const EOLSCardinalDirection direction, const float angle) const;

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Forward = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Backward_L = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Backward_R = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Right = nullptr;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Cycle Anim Set")
	TObjectPtr<class UAnimSequence> Left = nullptr;
};

USTRUCT(BlueprintType)
struct FOLSGaitAnimSet
{
	GENERATED_BODY()

public:

	FOLSGaitAnimSet()
	{
		PlayRate_Start = FVector2D(.8f, 1.2f);
		PlayRate_Pivot = FVector2D(.8f, 1.2f);
		PlayRate_Cycle = FVector2D(.8f, 1.2f);
	};

public:

	void GetPlayRateByLocomotionState(const EOLSLocomotionStatePlayRate& state, FVector2D& outPlayRate) const;
	
public:

	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	FVector2D PlayRate_Start = FVector2D::ZeroVector;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	FVector2D PlayRate_Pivot = FVector2D::ZeroVector;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	FVector2D PlayRate_Cycle = FVector2D::ZeroVector; 
};

USTRUCT(BlueprintType)
struct FOLSGaitAnimSet_ForwardFacing : public FOLSGaitAnimSet
{
	GENERATED_BODY()

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
	FOLSMovementAnimSet_ForwardFacing StartCycle;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
	TObjectPtr<class UAnimSequence> Cycle = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
	FOLSMovementAnimSet_ForwardFacing Pivot;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
	TObjectPtr<class UAnimSequence> StopCycle = nullptr;
};

USTRUCT(BlueprintType)
struct FOLSGaitAnimSet_CameraFacing : public FOLSGaitAnimSet
{
	GENERATED_BODY()

public:

	const FOLSMovementAnimSet& GetStartCycleFromHipDirection(const EOLSHipDirection hipDirection) const;
	const FOLSMovementAnimSet& GetCycleFromHipDirection(const EOLSHipDirection hipDirection) const;
	const FOLSMovementAnimSet& GetPivotFromHipDirection(const EOLSHipDirection hipDirection) const;
	const FOLSMovementAnimSet& GetStopCycleFromHipDirection(const EOLSHipDirection hipDirection) const;

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward")
	FOLSMovementAnimSet StartCycle_HipForward;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward")
	FOLSMovementAnimSet Cycle_HipForward;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward")
	FOLSMovementAnimSet Pivot_HipForward;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward")
	FOLSMovementAnimSet StopCycle_HipForward;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
	FOLSMovementAnimSet StartCycle_HipBackward;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
	FOLSMovementAnimSet Cycle_HipBackward;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
	FOLSMovementAnimSet Pivot_HipBackward;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
	FOLSMovementAnimSet StopCycle_HipBackward;
};

USTRUCT(BlueprintType)
struct FOLSGaitAnimSets
{
	GENERATED_BODY()

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Sets")
	FOLSGaitAnimSet_ForwardFacing GaitAnimSet_ForwardFacing;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Sets")
	FOLSGaitAnimSet_CameraFacing GaitAnimSet_CameraFacing;
};

USTRUCT(BlueprintType)
struct FOLSStanceAnimSets
{
	GENERATED_BODY()

public:

	class UAnimSequence* GetIdleAnimation(const bool isAiming) const;
	class UAnimSequence* GetIdleEntryAnimation() const;
	class UAnimSequence* GetRandomIdleBreakAnimation() const;
	bool CanPlayIdleBreakAnimation() const;
	class UAnimSequence* GetTurnInPlaceAnimation(const float direction) const;
	const FOLSGaitAnimSets* SelectGaitAnimSetByGait(const EOLSGait& gait) const;
	
public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	TMap<EOLSGait, FOLSGaitAnimSets> GaitAnimSets;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	FOLSIdleAndTurnInPlaceAnimSet IdleAndTurnInPlaceAnimSet;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	FOLSAimAnimSet AimAnimSet;
};

USTRUCT(BlueprintType)
struct FOLSRootYawOffsetClamp
{
	GENERATED_BODY()

public:

	const FVector2D& GetRootYawOffsetClamp(const EOLSStance stance) const;
	
public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Root Yaw Offset Clamp")
	FVector2D RootYawOffsetClamp_Standing = FVector2D::ZeroVector;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Root Yaw Offset Clamp")
	FVector2D RootYawOffsetClamp_Crouching = FVector2D::ZeroVector;
};

USTRUCT(BlueprintType)
struct FOLSRootYawOffsetClamps
{
	GENERATED_BODY()

public:

	const FOLSRootYawOffsetClamp& GetRootYawOffsetClamp(const EOLSRotationMode& rotationMode) const;
	
public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
	TMap<EOLSRotationMode, FOLSRootYawOffsetClamp> RootYawOffsetClamps;
};
