// © 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 "UObject/Object.h"
#include "OLSMaskAnimationData.generated.h"

//Enums
UENUM(BlueprintType)
enum class EOLSAdditiveMode : uint8
{
	EMeshSpace      UMETA(DisplayName = "MeshSpace"),
	ELocalSpace     UMETA(DisplayName = "LocalSpace"),
};

//Structs
USTRUCT(BlueprintType)
struct FOLSNodeMaskWeights
{
	GENERATED_BODY()

	UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config,meta=(ClampMin = "0.0" , ClampMax = "1.0") )
	float OverrideAlpha = 0.0f;

	UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config ,meta=(ClampMin = "0.0" , ClampMax = "1.0"))
	float AdditiveAlpha = 0.0f;

	UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config ,meta=(ClampMin = "0.0" , ClampMax = "1.0"))
	float MeshSpaceBlendAlpha = 1.0f;

	UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config ,meta=(ClampMin = "0.0" , ClampMax = "1.0"))
	float LocalSpaceBlendAlpha = 0.0f;
	
};

USTRUCT(BlueprintType)
struct FOLSMaskWeights
{
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves", meta=(ClampMin = "0.0", ClampMax = "1.0"))
	float MaskWeight = 0;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves", meta=(ClampMin = "0.0", ClampMax = "1.0"))
	float MaskAdditive = 0;
};

USTRUCT(BlueprintType)
struct FOLSArmMaskWeights
{
	GENERATED_BODY()

public:

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	EOLSAdditiveMode ArmAdditiveMode = EOLSAdditiveMode::ELocalSpace;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights MaskWeights;

	UPROPERTY(BlueprintReadOnly,Category = "Mask Curves")
	float ArmMeshSpaceBlend = 0.0f;

	UPROPERTY(BlueprintReadOnly,Category = "Mask Curves")
	float ArmLocalSpaceBlend = 0.0f;
};

USTRUCT(BlueprintType)
struct FOLSMaskingWeights
{
	GENERATED_BODY()

public:
	
	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights LegsWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights PelvisWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights SpineWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights HeadWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSArmMaskWeights RightArmWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights RightHandWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSArmMaskWeights LeftArmWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSMaskWeights LeftHandWeights;
	
};

USTRUCT(BlueprintType)
struct FOLSCapturedMaskingWeights
{
	GENERATED_BODY()

public:
	
	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights LegsWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights PelvisWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights SpineWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights HeadWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights RightArmWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights RightHandWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights LeftArmWeights;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves")
	FOLSNodeMaskWeights LeftHandWeights;
	
};

USTRUCT(BlueprintType)
struct FOLSMaskAnimation
{
	GENERATED_BODY()

public:
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation")
	TObjectPtr<class UAnimSequence> Animation = nullptr;

	UPROPERTY(BlueprintReadOnly, Category = "Masking Curves", meta = (HideDefault))
	FOLSCapturedMaskingWeights Weights;

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation")
	FOLSMaskingWeights MaskingWeights;

	UPROPERTY(BlueprintReadOnly, Category = "Masking Curves", meta = (HideDefault))
	TMap<FName, float> CurvesToModify;

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation")
	float MaskPoseTime = 0.f;
	
public:

#if WITH_EDITOR
	void CacheAdditiveCurves();
#endif
};

USTRUCT(BlueprintType)
struct FOLSGaitMasks
{
	GENERATED_BODY()

public:
	
	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation")
	FOLSMaskAnimation ForwardMask;
	
	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation")
	FOLSMaskAnimation RightMask;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation")
	FOLSMaskAnimation LeftMask;

	UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation")
	FOLSMaskAnimation BackwardMask;

public:
	
#if WITH_EDITOR
	void CacheAdditiveCurves();
#endif
};

USTRUCT(BlueprintType)
struct FOLSStanceMaskSets
{
	GENERATED_BODY()

public:

#if WITH_EDITOR
	void CacheAdditiveCurves();
#endif

	const FOLSGaitMasks* SelectGaitMasksByGait(const FGameplayTag& gait);
	const FOLSMaskAnimation& GetIdleMask() const;
	const FOLSMaskAnimation& GetAimMask() const;
	FORCEINLINE void GetAimBlendInOut(float& outBlendIn, float& outBlendOut) const;

public:
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets")
	TMap<FGameplayTag, FOLSGaitMasks> GaitMasks;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets")
	FOLSMaskAnimation IdleMask;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets")
	FOLSMaskAnimation AimMask;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets")
	float AimBlendInTime = .4f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets")
	float AimBlendOutTime = .4f;
};

// Legs
static const FName MaskLegsCurveName = FName("LegsMask");
static const FName MaskLegsLocalSpaceCurveName = FName("LegsMask_LS");
static const FName MaskLegsMeshSpaceCurveName = FName("LegsMask_MS");
static const FName MaskLegsAddCurveName = FName("LegsMask_Add");

// Pelvis
static const FName MaskPelvisCurveName = FName("PelvisMask");
static const FName MaskPelvisLocalSpaceCurveName = FName("PelvisMask_LS");
static const FName MaskPelvisMeshSpaceCurveName = FName("PelvisMask_MS");
static const FName MaskPelvisAddCurveName = FName("PelvisMask_Add");

// Spine
static const FName MaskSpineCurveName = FName("SpineMask");
static const FName MaskSpineLocalSpaceCurveName = FName("SpineMask_LS");
static const FName MaskSpineMeshSpaceCurveName = FName("SpineMask_MS");
static const FName MaskSpineAddCurveName = FName("SpineMask_Add");

// Head
static const FName MaskHeadCurveName = FName("HeadMask");
static const FName MaskHeadLocalSpaceCurveName = FName("HeadMask_LS");
static const FName MaskHeadMeshSpaceCurveName = FName("HeadMask_MS");
static const FName MaskHeadAddCurveName = FName("HeadMask_Add");

// Right Arm
static const FName MaskRightArmCurveName = FName("RightArmMask");
static const FName RightArmLocalSpaceCurveName = FName("RightArmMask_LS");
static const FName RightArmMeshSpaceCurveName = FName("RightArmMask_MS");
static const FName MaskRightArmAddCurveName = FName("RightArmMask_Add");

// Left Arm
static const FName MaskLeftArmCurveName = FName("LeftArmMask");
static const FName LeftArmLocalSpaceCurveName = FName("LeftArmMask_LS");
static const FName LeftArmMeshSpaceCurveName = FName("LeftArmMask_MS");
static const FName MaskLeftArmAddCurveName = FName("LeftArmMask_Add");

// Right Hand
static const FName RightHandCurveName = FName("RightHandMask");
static const FName RightHandLocalSpaceCurveName = FName("RightHandMask_LS");
static const FName RightHandMeshSpaceCurveName = FName("RightHandMask_MS");
static const FName MaskRightHandAddCurveName = FName("RightHandMask_Add");

// Left Hand
static const FName LeftHandCurveName = FName("LeftHandMask");
static const FName LeftHandLocalSpaceCurveName = FName("LeftHandMask_LS");
static const FName LeftHandMeshSpaceCurveName = FName("LeftHandMask_MS");
static const FName MaskLeftHandAddCurveName = FName("LeftHandMask_Add");

// Masking Group
static const FName MaskingGroupName = FName("Standing Mask");
