// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_PoseUtil
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class ProfileUtils_PoseUtil
{
    public BoneSpatialData GetBoneSpatialData(HumanBodyBones refBone, HumanBodyBones[] influencedBones, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes, bool addChildBones = false)
    {
        BoneSpatialData boneSpatialData = new BoneSpatialData();
        boneSpatialData.refBone = refBone;
        Transform baseBoneFromBoneMap = this.GetBaseBoneFromBoneMap(boneMap, refBone);
        if (baseBoneFromBoneMap == null)
        {
            return null;
        }
        List<Vector3> refVertices = this.GetRefVertices(influencedBones, boneMap, sourceBodyBakedMeshes, addChildBones);
        boneSpatialData.pcaData = this.GetPCAData(baseBoneFromBoneMap, refVertices);
        Transform baseBoneFromBoneMap2 = this.GetBaseBoneFromBoneMap(boneMap, HumanBodyBones.Hips);
        boneSpatialData.volumeData = this.GetVolumeData(baseBoneFromBoneMap, baseBoneFromBoneMap2, refVertices);
        return boneSpatialData;
    }

    private List<Vector3> GetRefVertices(HumanBodyBones[] influencedBones, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes, bool addChildBones = false, float weightThreshold = 0.15f, int sampleStep = 1)
    {
        List<Vector3> list = new List<Vector3>();
        HashSet<Transform> targetBoneSet = new HashSet<Transform>();
        foreach (HumanBodyBones key in influencedBones)
        {
            if (!boneMap.TryGetValue(key, out var value) || value == null)
            {
                continue;
            }
            foreach (Transform item in value)
            {
                if (item != null)
                {
                    targetBoneSet.Add(item);
                }
            }
        }
        if (targetBoneSet.Count == 0)
        {
            string text = string.Join(", ", influencedBones.Select((HumanBodyBones b) => b.ToString()));
            Debug.LogError("[ProfileSaver_PoseUtil] CollectBodyPartVerticesWorld: targetBoneSet is empty.\nMissing Humanoid Set : " + text);
            return list;
        }
        if (addChildBones)
        {
            Transform[] array = targetBoneSet.ToArray();
            targetBoneSet.Clear();
            Transform[] array2 = array;
            for (int i = 0; i < array2.Length; i++)
            {
                AddDescendants(array2[i]);
            }
        }
        foreach (ProfileBakedBodyMesh sourceBodyBakedMesh in sourceBodyBakedMeshes)
        {
            BoneWeight[] boneWeights = sourceBodyBakedMesh.boneWeights;
            Transform[] bones = sourceBodyBakedMesh.bones;
            if (boneWeights == null || boneWeights.Length == 0 || bones == null || bones.Length == 0)
            {
                continue;
            }
            Vector3[] worldVertices = sourceBodyBakedMesh.worldVertices;
            if (worldVertices == null || worldVertices.Length == 0)
            {
                continue;
            }
            int num = Mathf.Min(worldVertices.Length, boneWeights.Length);
            for (int num2 = 0; num2 < num; num2 += sampleStep)
            {
                BoneWeight boneWeight = boneWeights[num2];
                float wSum = 0f;
                Acc(boneWeight.boneIndex0, boneWeight.weight0);
                Acc(boneWeight.boneIndex1, boneWeight.weight1);
                Acc(boneWeight.boneIndex2, boneWeight.weight2);
                Acc(boneWeight.boneIndex3, boneWeight.weight3);
                if (!(wSum < weightThreshold))
                {
                    list.Add(worldVertices[num2]);
                }
                void Acc(int index, float w)
                {
                    if (index >= 0 && index < bones.Length && !(w <= 0f))
                    {
                        Transform transform = bones[index];
                        if (transform != null && targetBoneSet.Contains(transform))
                        {
                            wSum += w;
                        }
                    }
                }
            }
        }
        return list;
        void AddDescendants(Transform t)
        {
            if (!(t == null) && targetBoneSet.Add(t))
            {
                for (int j = 0; j < t.childCount; j++)
                {
                    AddDescendants(t.GetChild(j));
                }
            }
        }
    }

    private PCAData GetPCAData(Transform originTransform, List<Vector3> points)
    {
        PCAData pCAData = new ProfileUtils_PCAUtil().ComputeRegionStats(points);
        if (originTransform == null)
        {
            return pCAData;
        }
        PCAData result = new PCAData
        {
            pcaCenter = originTransform.InverseTransformPoint(pCAData.pcaCenter),
            pcaPrincipalAxis = originTransform.InverseTransformDirection(pCAData.pcaPrincipalAxis).normalized,
            pcaLength = pCAData.pcaLength,
            pcaAvgRadius = pCAData.pcaAvgRadius
        };
        if (Mathf.Abs(pCAData.pcaLength) < 0.0001f)
        {
            Debug.LogWarning("[ProfileUtils_PoseUtil] GetPCAData - " + originTransform.name + " Pca Length is to Small");
        }
        return result;
    }

    private VolumeData GetVolumeData(Transform originTransform, Transform axisTransform, List<Vector3> points)
    {
        return new ProfileUtils_VolumeUtil().GetVolumeData(originTransform, axisTransform, points);
    }

    private Transform GetBaseBoneFromBoneMap(Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, HumanBodyBones bone)
    {
        if (boneMap == null || !boneMap.TryGetValue(bone, out var value) || value == null)
        {
            return null;
        }
        return value.FirstOrDefault();
    }
}
