// Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,
// for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.
// EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.BodyPoseMatch_Arm
using System.Collections.Generic;
using UnityEngine;

public class BodyPoseMatch_Arm
{
    private readonly BodyPoseMatch_CommonUtil poseMatchCommonUtil;

    public BodyPoseMatch_Arm()
    {
        this.poseMatchCommonUtil = new BodyPoseMatch_CommonUtil();
    }

    public void AlignUpperArmByArmCenters(IReadOnlyCollection<Transform> sourceLeftUpperArmSet, IReadOnlyCollection<Transform> sourceRightUpperArmSet, Vector3 sourceShoulderCenterWorld, Vector3 targetShoulderCenterWorld, Transform axisReferenceTransform, bool lockRightAxis = true)
    {
        if (sourceLeftUpperArmSet == null || sourceLeftUpperArmSet.Count == 0)
        {
            throw new AutoMorpherException("Source Left UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmCenters\n - sourceLeftUpperArmSet is null or empty");
        }
        if (sourceRightUpperArmSet == null || sourceRightUpperArmSet.Count == 0)
        {
            throw new AutoMorpherException("Source Right UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmCenters\n - sourceRightUpperArmSet is null or empty");
        }
        if (axisReferenceTransform == null)
        {
            throw new AutoMorpherException("Axis Reference Transform is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmCenters\n - axisReferenceTransform is null");
        }
        Vector3 vector = targetShoulderCenterWorld - sourceShoulderCenterWorld;
        if (lockRightAxis)
        {
            Vector3 right = axisReferenceTransform.right;
            float num = Vector3.Dot(vector, right);
            vector -= right * num;
        }
        foreach (Transform item in sourceLeftUpperArmSet)
        {
            if (!(item == null))
            {
                item.position += vector;
            }
        }
        foreach (Transform item2 in sourceRightUpperArmSet)
        {
            if (!(item2 == null))
            {
                item2.position += vector;
            }
        }
    }

    public void AlignUpperArmByArmPcaCenters(IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap)
    {
        if (proxyBoneMap == null)
        {
            throw new AutoMorpherException("Proxy Bone Map is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap is null");
        }
        Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, HumanBodyBones.Hips);
        if (boneFromBoneMap == null)
        {
            throw new AutoMorpherException("Proxy Hips is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxy hips transform is null");
        }
        RegionStats regionStats = this.ComputeArmRegionStats(proxyBakedBodyMeshes, proxyBoneMap, isLeft: true);
        RegionStats regionStats2 = this.ComputeArmRegionStats(proxyBakedBodyMeshes, proxyBoneMap, isLeft: false);
        bool flag = regionStats.length > 0.0001f;
        bool flag2 = regionStats2.length > 0.0001f;
        if (!flag && !flag2)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: proxy arm PCA failed. Skip.");
            return;
        }
        Vector3 sourceShoulderCenterWorld = this.CalculateShoulderCenter(flag, flag2, regionStats.center, regionStats2.center);
        RegionStats regionStats3 = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: true);
        RegionStats regionStats4 = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: false);
        bool flag3 = regionStats3.length > 0.0001f;
        bool flag4 = regionStats4.length > 0.0001f;
        if (!flag3 && !flag4)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: target arm PCA failed. Skip.");
            return;
        }
        Vector3 targetShoulderCenterWorld = this.CalculateShoulderCenter(flag3, flag4, regionStats3.center, regionStats4.center);
        if (!proxyBoneMap.TryGetValue(HumanBodyBones.LeftUpperArm, out var value) || value == null || value.Count == 0)
        {
            throw new AutoMorpherException("Proxy Left UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap has no LeftUpperArm set");
        }
        if (!proxyBoneMap.TryGetValue(HumanBodyBones.RightUpperArm, out var value2) || value2 == null || value2.Count == 0)
        {
            throw new AutoMorpherException("Proxy Right UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap has no RightUpperArm set");
        }
        this.AlignUpperArmByArmCenters(value, value2, sourceShoulderCenterWorld, targetShoulderCenterWorld, boneFromBoneMap);
    }

    public void AlignUpperArmByArmPcaCenters(IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, Transform clothesTransform, ProfileData profileData, Vector3 comprehensiveScale)
    {
        if (clothBoneMap == null)
        {
            throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - clothBoneMap is null");
        }
        if (profileData == null)
        {
            throw new AutoMorpherException("Profile Data is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - profileData is null");
        }
        Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, HumanBodyBones.Hips);
        if (boneFromBoneMap == null)
        {
            throw new AutoMorpherException("Cloth Hips is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - cloth hips transform is null");
        }
        bool flag = profileData.LeftUpperArmSpatialData != null && profileData.LeftUpperArmSpatialData.pcaData != null && profileData.LeftUpperArmSpatialData.pcaData.pcaLength > 0.0001f;
        bool flag2 = profileData.RightUpperArmSpatialData != null && profileData.RightUpperArmSpatialData.pcaData != null && profileData.RightUpperArmSpatialData.pcaData.pcaLength > 0.0001f;
        if (!flag && !flag2)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: profile arm data invalid. Skip.");
            return;
        }
        Vector3 leftCenter = Vector3.zero;
        if (flag)
        {
            leftCenter = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, profileData.LeftUpperArmSpatialData, comprehensiveScale);
        }
        Vector3 rightCenter = Vector3.zero;
        if (flag2)
        {
            rightCenter = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, profileData.RightUpperArmSpatialData, comprehensiveScale);
        }
        Vector3 sourceShoulderCenterWorld = this.CalculateShoulderCenter(flag, flag2, leftCenter, rightCenter);
        RegionStats regionStats = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: true);
        RegionStats regionStats2 = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: false);
        bool flag3 = regionStats.length > 0.0001f;
        bool flag4 = regionStats2.length > 0.0001f;
        if (!flag3 && !flag4)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: target arm PCA failed. Skip.");
            return;
        }
        Vector3 targetShoulderCenterWorld = this.CalculateShoulderCenter(flag3, flag4, regionStats.center, regionStats2.center);
        if (!clothBoneMap.TryGetValue(HumanBodyBones.LeftUpperArm, out var value) || value == null || value.Count == 0)
        {
            throw new AutoMorpherException("Cloth Left UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - clothBoneMap has no LeftUpperArm set");
        }
        if (!clothBoneMap.TryGetValue(HumanBodyBones.RightUpperArm, out var value2) || value2 == null || value2.Count == 0)
        {
            throw new AutoMorpherException("Cloth Right UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - clothBoneMap has no RightUpperArm set");
        }
        this.AlignUpperArmByArmCenters(value, value2, sourceShoulderCenterWorld, targetShoulderCenterWorld, boneFromBoneMap);
    }

    private Vector3 CalculateShoulderCenter(bool leftValid, bool rightValid, Vector3 leftCenter, Vector3 rightCenter)
    {
        if (leftValid && rightValid)
        {
            return 0.5f * (leftCenter + rightCenter);
        }
        if (leftValid)
        {
            return leftCenter;
        }
        return rightCenter;
    }

    public RegionStats ComputeArmRegionStats(IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft)
    {
        HumanBodyBones[] targetHumanBones = ((!isLeft) ? new HumanBodyBones[3]
        {
            HumanBodyBones.RightUpperArm,
            HumanBodyBones.RightLowerArm,
            HumanBodyBones.RightHand
        } : new HumanBodyBones[3]
        {
            HumanBodyBones.LeftUpperArm,
            HumanBodyBones.LeftLowerArm,
            HumanBodyBones.LeftHand
        });
        List<Vector3> list = this.poseMatchCommonUtil.CollectHumanoidVerticesWorld(targetHumanBones, avatarBakedBodyMeshes, avatarBoneMap);
        if (list == null || list.Count == 0)
        {
            Debug.LogWarning($"[BodyPoseMatch_Arm] ComputeArmRegionStats: arm vertices 0. isLeft={isLeft}");
            return default(RegionStats);
        }
        RegionStats result = new PcaUtil().ComputeRegionStats(list);
        Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftUpperArm : HumanBodyBones.RightUpperArm);
        Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
        Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
        Vector3 principalAxis = Vector3.zero;
        if (boneFromBoneMap != null && boneFromBoneMap3 != null)
        {
            principalAxis = boneFromBoneMap3.position - boneFromBoneMap.position;
        }
        else if (boneFromBoneMap != null && boneFromBoneMap2 != null)
        {
            principalAxis = boneFromBoneMap2.position - boneFromBoneMap.position;
        }
        else if (boneFromBoneMap2 != null && boneFromBoneMap3 != null)
        {
            principalAxis = boneFromBoneMap3.position - boneFromBoneMap2.position;
        }
        if (principalAxis.sqrMagnitude > 1E-08f)
        {
            principalAxis.Normalize();
            result.principalAxis = principalAxis;
        }
        return result;
    }

    private void ScalingUpperArmLength(Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft, bool autoDetectAxis, int forceAxisIndex)
    {
        HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftUpperArm : HumanBodyBones.RightUpperArm);
        HumanBodyBones bone = (isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
        HumanBodyBones bone2 = (isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
        Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, humanBodyBones);
        Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, bone);
        Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, bone2);
        Transform boneFromBoneMap4 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
        Transform boneFromBoneMap5 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, bone);
        Transform boneFromBoneMap6 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, bone2);
        HashSet<Transform> value;
        if (boneFromBoneMap == null || boneFromBoneMap2 == null || boneFromBoneMap3 == null || boneFromBoneMap4 == null || boneFromBoneMap5 == null || boneFromBoneMap6 == null)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingSingArmLenght: some arm bones are null. Skip.");
        }
        else if (sourceBoneMap == null || !sourceBoneMap.TryGetValue(humanBodyBones, out value) || value == null || value.Count == 0)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingSingArmLenght: sourceUpperSet missing. Skip.");
        }
        else
        {
            this.poseMatchCommonUtil.BoneLengthAdjust(boneFromBoneMap, boneFromBoneMap2, boneFromBoneMap4, boneFromBoneMap5, value, autoDetectAxis, forceAxisIndex);
        }
    }

    private void ScalingLowerArmLength(Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft, bool autoDetectAxis, int forceAxisIndex, float sourceLowerarmExtremeX, float targetLowerarmExtremeX)
    {
        HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
        HumanBodyBones bone = (isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
        Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, humanBodyBones);
        Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, bone);
        Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
        if (boneFromBoneMap == null || boneFromBoneMap2 == null || boneFromBoneMap3 == null)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingSingArmLenght: some arm bones are null. Skip.");
            return;
        }
        float x = boneFromBoneMap.position.x;
        float x2 = boneFromBoneMap3.position.x;
        float num = Mathf.Abs(sourceLowerarmExtremeX - x);
        float num2 = Mathf.Abs(targetLowerarmExtremeX - x2);
        if (num < 0.0001f || num2 < 0.0001f)
        {
            Debug.LogWarning($"[BodyPoseMatch_Arm] ScalingSingArmLenght: span too small. source={num}, target={num2}");
            return;
        }
        float num3 = num2 / num;
        int num4 = this.ResolveArmLengthAxisIndex(boneFromBoneMap, boneFromBoneMap2, autoDetectAxis, forceAxisIndex);
        Vector3 localScale = boneFromBoneMap.localScale;
        switch (num4)
        {
            case 0:
                localScale.x *= num3;
                break;
            case 1:
                localScale.y *= num3;
                break;
            case 2:
                localScale.z *= num3;
                break;
        }
        foreach (Transform item in sourceBoneMap[humanBodyBones])
        {
            if (!(item == null))
            {
                item.localScale = localScale;
            }
        }
    }

    public void ScalingBothArmsLength(IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool autoDetectAxis = true, int forceAxisIndex = 1)
    {
        if (proxyBoneMap == null || targetBoneMap == null)
        {
            throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_Arm] ScalingSingArmLenght\n - BoneMap is null");
        }
        this.ScalingUpperArmLength(proxyBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex);
        this.ScalingUpperArmLength(proxyBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex);
        if (proxyBakedBodyMeshes != null)
        {
            foreach (BakedBodyMesh proxyBakedBodyMesh in proxyBakedBodyMeshes)
            {
                proxyBakedBodyMesh.ReBakeMesh();
            }
        }
        this.ScalingLowerArmLength_BodyMatch(proxyBakedBodyMeshes, proxyBoneMap, targetBakedBodyMeshes, targetBoneMap, autoDetectAxis, forceAxisIndex);
    }

    private void ScalingLowerArmLength_BodyMatch(IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool autoDetectAxis, int forceAxisIndex)
    {
        if (this.TryGetForearmExtremeX(proxyBakedBodyMeshes, proxyBoneMap, HumanBodyBones.LeftHand, isLeft: true, out var extremeX) && this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.LeftHand, isLeft: true, out var extremeX2))
        {
            this.ScalingLowerArmLength(proxyBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex, extremeX, extremeX2);
        }
        else
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_BodyMatch: left extreme calc failed. Skip left lower.");
        }
        if (this.TryGetForearmExtremeX(proxyBakedBodyMeshes, proxyBoneMap, HumanBodyBones.RightHand, isLeft: false, out var extremeX3) && this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.RightHand, isLeft: false, out var extremeX4))
        {
            this.ScalingLowerArmLength(proxyBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex, extremeX3, extremeX4);
        }
        else
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_BodyMatch: right extreme calc failed. Skip right lower.");
        }
    }

    public void ScalingBothArmsLength(IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale, bool autoDetectAxis = true, int forceAxisIndex = 1)
    {
        if (clothBoneMap == null || targetBoneMap == null)
        {
            throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_Arm] ScalingSingArmLenght\n - BoneMap is null");
        }
        if (profileData == null)
        {
            throw new AutoMorpherException("Profile Data is Missing", "[BodyPoseMatch_Arm] ScalingSingArmLenght\n - profileData is null");
        }
        this.ScalingUpperArmLength(clothBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex);
        this.ScalingUpperArmLength(clothBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex);
        this.ScalingLowerArmLength_ProfileMatch(targetBakedBodyMeshes, targetBoneMap, clothBoneMap, profileData, comprehensiveScale, autoDetectAxis, forceAxisIndex);
    }

    private void ScalingLowerArmLength_ProfileMatch(IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale, bool autoDetectAxis, int forceAxisIndex)
    {
        float extremeX;
        if (profileData.LeftLowerArm_HandSpatialData == null || profileData.LeftLowerArm_HandSpatialData.volumeData == null)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: left spatial data missing. Skip left lower.");
        }
        else if (this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.LeftHand, isLeft: true, out extremeX))
        {
            float profileForearmExtremeX = this.GetProfileForearmExtremeX(clothBoneMap, profileData.LeftLowerArm_HandSpatialData, comprehensiveScale, isLeft: true);
            this.ScalingLowerArmLength(clothBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex, profileForearmExtremeX, extremeX);
        }
        else
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: left target extreme calc failed. Skip left lower.");
        }
        float extremeX2;
        if (profileData.RightLowerArm_HandSpatialData == null || profileData.RightLowerArm_HandSpatialData.volumeData == null)
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: right spatial data missing. Skip right lower.");
        }
        else if (this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.RightHand, isLeft: false, out extremeX2))
        {
            float profileForearmExtremeX2 = this.GetProfileForearmExtremeX(clothBoneMap, profileData.RightLowerArm_HandSpatialData, comprehensiveScale, isLeft: false);
            this.ScalingLowerArmLength(clothBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex, profileForearmExtremeX2, extremeX2);
        }
        else
        {
            Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: right target extreme calc failed. Skip right lower.");
        }
    }

    private bool TryGetForearmExtremeX(IReadOnlyList<BakedBodyMesh> bakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, HumanBodyBones targetBone, bool isLeft, out float extremeX, float weightThreshold = 0.15f, int sampleStep = 1)
    {
        extremeX = (isLeft ? float.PositiveInfinity : float.NegativeInfinity);
        if (bakedBodyMeshes == null || boneMap == null)
        {
            return false;
        }
        if (!boneMap.TryGetValue(targetBone, out var value) || value == null || value.Count == 0)
        {
            return false;
        }
        List<Vector3> list = this.poseMatchCommonUtil.CollectWeightedVerticesWorld(bakedBodyMeshes, value, weightThreshold, sampleStep);
        if (list == null || list.Count == 0)
        {
            return false;
        }
        for (int i = 0; i < list.Count; i++)
        {
            float x = list[i].x;
            if (isLeft)
            {
                if (x < extremeX)
                {
                    extremeX = x;
                }
            }
            else if (x > extremeX)
            {
                extremeX = x;
            }
        }
        return true;
    }

    private float GetProfileForearmExtremeX(Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, BoneSpatialData spatialData, Vector3 comprehensiveScale, bool isLeft)
    {
        if (spatialData == null || spatialData.volumeData == null)
        {
            throw new AutoMorpherException("Profile Volume Data is Missing", "[BodyPoseMatch_Arm] GetProfileForearmExtremeX\n - spatialData or spatialData.volumeData is null");
        }
        if (this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, spatialData.refBone) == null)
        {
            throw new AutoMorpherException("Profile Ref Bone Transform is Missing", "[BodyPoseMatch_Arm] GetProfileForearmExtremeX\n - refBone transform is null");
        }
        BodyPoseMatch_CommonUtil bodyPoseMatch_CommonUtil = new BodyPoseMatch_CommonUtil();
        float x = bodyPoseMatch_CommonUtil.GetProfileVolumeMinWorld(clothBoneMap, spatialData, 1, comprehensiveScale).x;
        float x2 = bodyPoseMatch_CommonUtil.GetProfileVolumeMaxWorld(clothBoneMap, spatialData, 1, comprehensiveScale).x;
        if (!isLeft)
        {
            return x2;
        }
        return x;
    }

    private int ResolveArmLengthAxisIndex(Transform lowerArm, Transform hand, bool autoDetectAxis, int forceAxisIndex)
    {
        if (!autoDetectAxis)
        {
            return Mathf.Clamp(forceAxisIndex, 0, 2);
        }
        Vector3 direction = hand.position - lowerArm.position;
        Vector3 vector = lowerArm.InverseTransformDirection(direction);
        float num = Mathf.Abs(vector.x);
        float num2 = Mathf.Abs(vector.y);
        float num3 = Mathf.Abs(vector.z);
        if (num2 >= num && num2 >= num3)
        {
            return 1;
        }
        if (num >= num3)
        {
            return 0;
        }
        return 2;
    }

    public void DrawArmPcaDebug(GameObject avatarObject, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft, Color centerColor, Color axisColor, float axisScale = 1f, float duration = 0.1f)
    {
        if (avatarBakedBodyMeshes != null && avatarBoneMap != null)
        {
            RegionStats regionStats = this.ComputeArmRegionStats(avatarBakedBodyMeshes, avatarBoneMap, isLeft);
            if (!(regionStats.length < 0.0001f))
            {
                Vector3 center = regionStats.center;
                Vector3 vector = ((regionStats.principalAxis.sqrMagnitude > 1E-08f) ? regionStats.principalAxis.normalized : Vector3.up);
                float num = 0.02f * axisScale;
                Debug.DrawLine(center + Vector3.up * num, center - Vector3.up * num, centerColor, duration);
                Debug.DrawLine(center + Vector3.right * num, center - Vector3.right * num, centerColor, duration);
                Debug.DrawLine(center + Vector3.forward * num, center - Vector3.forward * num, centerColor, duration);
                float num2 = regionStats.length * 0.5f * axisScale;
                Debug.DrawLine(center - vector * num2, center + vector * num2, axisColor, duration);
            }
        }
    }

    public void DrawForearmExtremeDebugPair(GameObject proxyObject, IReadOnlyList<SkinnedMeshRenderer> proxyBodyMeshes, GameObject targetObject, IReadOnlyList<SkinnedMeshRenderer> targetBodyMeshes, bool isLeft, float size = 0.03f, float duration = 3f)
    {
        this.DrawForearmExtremeDebugSingle(proxyObject, proxyBodyMeshes, isLeft, Color.blue, Color.cyan, size, duration);
        this.DrawForearmExtremeDebugSingle(targetObject, targetBodyMeshes, isLeft, Color.red, Color.magenta, size, duration);
    }

    public void DrawForearmExtremeDebugSingle(GameObject avatarObject, IReadOnlyList<SkinnedMeshRenderer> bodyMeshes, bool isLeft, Color lineColor, Color pointColor, float size = 0.03f, float duration = 3f)
    {
        if (avatarObject == null || bodyMeshes == null || bodyMeshes.Count == 0)
        {
            return;
        }
        Animator component = avatarObject.GetComponent<Animator>();
        if (!(component == null))
        {
            HumanBodyBones humanBoneId = (isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
            Transform boneTransform = component.GetBoneTransform(humanBoneId);
            if (boneTransform == null)
            {
                Debug.LogWarning($"[BodyPoseMatch_Arm] DrawForearmExtremeDebugSingle: elbow bone missing. isLeft={isLeft}");
                return;
            }
            if (!this.TryGetForearmExtremePoint(component, bodyMeshes, isLeft, out var extremePos))
            {
                Debug.LogWarning($"[BodyPoseMatch_Arm] DrawForearmExtremeDebugSingle: extreme vertex not found. isLeft={isLeft}");
                return;
            }
            Debug.DrawLine(boneTransform.position, extremePos, lineColor, duration);
            Debug.DrawLine(extremePos + Vector3.up * size, extremePos - Vector3.up * size, pointColor, duration);
            Debug.DrawLine(extremePos + Vector3.right * size, extremePos - Vector3.right * size, pointColor, duration);
            Debug.DrawLine(extremePos + Vector3.forward * size, extremePos - Vector3.forward * size, pointColor, duration);
        }
    }

    private bool TryGetForearmExtremePoint(Animator avatar, IReadOnlyList<SkinnedMeshRenderer> bodyMeshes, bool isLeft, out Vector3 extremePos)
    {
        extremePos = default(Vector3);
        if (avatar == null || bodyMeshes == null || bodyMeshes.Count == 0)
        {
            return false;
        }
        HumanBodyBones humanBoneId = (isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
        Transform boneTransform = avatar.GetBoneTransform(humanBoneId);
        if (boneTransform == null)
        {
            return false;
        }
        HashSet<Transform> targetBoneSet = new HashSet<Transform> { boneTransform };
        List<BakedBodyMesh> list = new List<BakedBodyMesh>(bodyMeshes.Count);
        for (int i = 0; i < bodyMeshes.Count; i++)
        {
            SkinnedMeshRenderer skinnedMeshRenderer = bodyMeshes[i];
            if (!(skinnedMeshRenderer == null))
            {
                BakedBodyMesh bakedBodyMesh = new BakedBodyMesh(skinnedMeshRenderer);
                bakedBodyMesh.ReBakeMesh();
                list.Add(bakedBodyMesh);
            }
        }
        if (list.Count == 0)
        {
            return false;
        }
        List<Vector3> list2 = this.poseMatchCommonUtil.CollectWeightedVerticesWorld(list, targetBoneSet, 0.1f);
        if (list2 == null || list2.Count == 0)
        {
            return false;
        }
        bool flag = false;
        float num = (isLeft ? float.PositiveInfinity : float.NegativeInfinity);
        for (int j = 0; j < list2.Count; j++)
        {
            Vector3 vector = list2[j];
            float x = vector.x;
            if (!flag)
            {
                flag = true;
                num = x;
                extremePos = vector;
            }
            else if (isLeft)
            {
                if (x < num)
                {
                    num = x;
                    extremePos = vector;
                }
            }
            else if (x > num)
            {
                num = x;
                extremePos = vector;
            }
        }
        return flag;
    }
}
