//======================================================================================================
// Company Name:       MotionTechnologies.inc
// Copyright Year:     2025
// File:               MoABoneMapping.h
//======================================================================================================

#pragma once

#include "CoreMinimal.h"
#include "MoABoneMapping.generated.h"

UENUM(BlueprintType)
enum class EMoABoneCategory : uint8
{
    BodyAndSpine    UMETA(DisplayName = "Body & Spine"),
    Legs            UMETA(DisplayName = "Legs"),
    Arms            UMETA(DisplayName = "Arms"),
    Fingers         UMETA(DisplayName = "Fingers")
};

UENUM(BlueprintType)
enum class EMoABoneName : uint8
{
    Hips                UMETA(DisplayName = "Pelvis"),
    Chest               UMETA(DisplayName = "Spine 01"),
    Chest1              UMETA(DisplayName = "Spine 02"),
    Chest2              UMETA(DisplayName = "Spine 03"),
    Neck                UMETA(DisplayName = "Neck 01"),
    Neck1               UMETA(DisplayName = "Head"),
    LeftHip             UMETA(DisplayName = "Thigh L"),
    LeftKnee            UMETA(DisplayName = "Calf L"),
    LeftAnkle           UMETA(DisplayName = "Foot L"),
    LeftToe             UMETA(DisplayName = "Toe L"),
    RightHip            UMETA(DisplayName = "Thigh R"),
    RightKnee           UMETA(DisplayName = "Calf R"),
    RightAnkle          UMETA(DisplayName = "Foot R"),
    RightToe            UMETA(DisplayName = "Toe R"),
    LeftCollar          UMETA(DisplayName = "Clavicle L"),
    LeftShoulder        UMETA(DisplayName = "UpperArm L"),
    LeftElbow           UMETA(DisplayName = "LowerArm L"),
    LeftWrist           UMETA(DisplayName = "Hand L"),
    RightCollar         UMETA(DisplayName = "Clavicle R"),
    RightShoulder       UMETA(DisplayName = "UpperArm R"),
    RightElbow          UMETA(DisplayName = "LowerArm R"),
    RightWrist          UMETA(DisplayName = "Hand R"),
    LeftFinger0         UMETA(DisplayName = "Thumb 01 L"),
    LeftFinger01        UMETA(DisplayName = "Thumb 02 L"),
    LeftFinger02        UMETA(DisplayName = "Thumb 03 L"),
    LeftFinger1         UMETA(DisplayName = "Index 01 L"),
    LeftFinger11        UMETA(DisplayName = "Index 02 L"),
    LeftFinger12        UMETA(DisplayName = "Index 03 L"),
    LeftFinger2         UMETA(DisplayName = "Middle 01 L"),
    LeftFinger21        UMETA(DisplayName = "Middle 02 L"),
    LeftFinger22        UMETA(DisplayName = "Middle 03 L"),
    LeftFinger3         UMETA(DisplayName = "Ring 01 L"),
    LeftFinger31        UMETA(DisplayName = "Ring 02 L"),
    LeftFinger32        UMETA(DisplayName = "Ring 03 L"),
    LeftFinger4         UMETA(DisplayName = "Pinky 01 L"),
    LeftFinger41        UMETA(DisplayName = "Pinky 02 L"),
    LeftFinger42        UMETA(DisplayName = "Pinky 03 L"),
    RightFinger0        UMETA(DisplayName = "Thumb 01 R"),
    RightFinger01       UMETA(DisplayName = "Thumb 02 R"),
    RightFinger02       UMETA(DisplayName = "Thumb 03 R"),
    RightFinger1        UMETA(DisplayName = "Index 01 R"),
    RightFinger11       UMETA(DisplayName = "Index 02 R"),
    RightFinger12       UMETA(DisplayName = "Index 03 R"),
    RightFinger2        UMETA(DisplayName = "Middle 01 R"),
    RightFinger21       UMETA(DisplayName = "Middle 02 R"),
    RightFinger22       UMETA(DisplayName = "Middle 03 R"),
    RightFinger3        UMETA(DisplayName = "Ring 01 R"),
    RightFinger31       UMETA(DisplayName = "Ring 02 R"),
    RightFinger32       UMETA(DisplayName = "Ring 03 R"),
    RightFinger4        UMETA(DisplayName = "Pinky 01 R"),
    RightFinger41       UMETA(DisplayName = "Pinky 02 R"),
    RightFinger42       UMETA(DisplayName = "Pinky 03 R"),
    Count               UMETA(Hidden)
};

USTRUCT(BlueprintType)
struct FMoABoneMappingRow
{
    GENERATED_USTRUCT_BODY()

public:
    FMoABoneMappingRow()
        : SourceBone(EMoABoneName::Hips)
        , TargetBone(NAME_None)
    {}

    FMoABoneMappingRow(EMoABoneName source, FName target)
        : SourceBone(source)
        , TargetBone(target)
    {}

    UPROPERTY(VisibleAnywhere, Category = "Bone Mapping", meta = (DisplayName = "Source (MoA)"))
    EMoABoneName SourceBone;

    UPROPERTY(EditAnywhere, Category = "Bone Mapping", meta = (DisplayName = "Target (Unreal)"))
    FName TargetBone;

    bool operator==(const FMoABoneMappingRow& Other) const
    {
        return (SourceBone == Other.SourceBone);
    }

    FString ToString() const
    {
        const UEnum* EnumPtr = StaticEnum<EMoABoneName>();
        FString SourceName = EnumPtr ? EnumPtr->GetNameStringByValue((int64)SourceBone) : TEXT("Unknown");
        FString TargetName = TargetBone.IsNone() ? TEXT("None") : TargetBone.ToString();
        return FString::Printf(TEXT("%s ¡æ %s"), *SourceName, *TargetName);
    }

    bool ExportTextItem(FString& ValueStr, FMoABoneMappingRow const& DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope) const
    {
        const UEnum* EnumPtr = StaticEnum<EMoABoneName>();
        FString SourceName = EnumPtr ? EnumPtr->GetDisplayNameTextByValue((int64)SourceBone).ToString() : TEXT("Unknown");
        ValueStr = SourceName;
        return true;
    }
};

class MOALIVELINK_API FMoABoneNameUtils
{
public:
    static FName EnumToFName(EMoABoneName BoneEnum);
    static EMoABoneName FNameToEnum(FName BoneName);
    static TArray<EMoABoneName> GetAllBoneEnums();
    static EMoABoneCategory GetBoneCategory(EMoABoneName BoneEnum);
    static FString GetCategoryName(EMoABoneCategory Category);
};

