// Copyright 2015 Noitom Technology Co., Ltd. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "CommonType.h"
#include "BoneLists.h"
#include "BoneNameContainer.h"
#include "UObject/ScriptMacros.h"
#include "BoneMappingInfo.generated.h"


/************************************************************************/
/* Structs in this file is just in internal plugin sharing                                                                     */
/************************************************************************/

USTRUCT(BlueprintType)
struct MOTIONCAPTURERUNTIME_API FBoneMappingInfo
{
	GENERATED_USTRUCT_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MotionCapture")
	TEnumAsByte<EMCBones::Type> PNID;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MotionCapture")
	FName CTName;

	FBoneMappingInfo();

	FBoneMappingInfo(EMCBones::Type InPNID, const FName& InCTName);

};


UCLASS(BlueprintType)
class MOTIONCAPTURERUNTIME_API UBoneMappingInfoWrapper : public UObject
{
	GENERATED_BODY()

public:
	UBoneMappingInfoWrapper( const FObjectInitializer& ObjectInitializer )
		: Super( ObjectInitializer )
	{
		bMappingSet = false;
		bWorldRefPoseEvaluated = false;
		bLocalRefPoseEvaluated = false;
	}

	UFUNCTION(BlueprintCallable, Category = "MotionCapture")
		void BoneNameOfEMCBone( EMCBones::Type Bone, FName& Name );

	UFUNCTION( BlueprintCallable, Category = "MotionCapture" )
		void BoneIndexOfEMCBone( EMCBones::Type Bone, int32& Index );

	UFUNCTION( BlueprintCallable, Category = "MotionCapture" )
		const TArray<FTransform>& LocalRefPose( );

	UFUNCTION( BlueprintCallable, Category = "MotionCapture" )
		const TArray<FTransform>& WorldRefPose( );

	UFUNCTION( BlueprintCallable, Category = "MotionCapture" )
		void LocalPose2World( const TArray<FTransform>& LocalPose, TArray<FTransform>& WorldPose );

	UFUNCTION( BlueprintCallable, Category = "MotionCapture" )
		bool PreEvaluatePose(
			EGloveMod Glove,
			FName AvatarName, 
			TArray<FTransform>& LocalPose,
			TArray<FTransform>& WorldPose );

public:
	UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "MotionCapture" )
		TArray<FBoneMappingInfo> BoneMap;

	UPROPERTY( EditAnywhere, BlueprintReadOnly, Category = "MotionCapture" )
		USkeletalMeshComponent* SkeletalMeshComp;

public:
	bool bMappingSet;
	FPNMultiMap BoneID2NameMap;

private:
	bool bWorldRefPoseEvaluated;
	TArray<FTransform> _WorldRefPose;

	bool bLocalRefPoseEvaluated;
	TArray<FTransform> _LocalRefPose;
};


FORCEINLINE bool operator==(const FBoneMappingInfo& Left, const FBoneMappingInfo& Right)
{
	return (Left.PNID == Right.PNID) && (Left.CTName == Right.CTName);
}

FORCEINLINE bool operator!=(const FBoneMappingInfo& Left, const FBoneMappingInfo& Right)
{
	return !(Left == Right);
}
