// 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.BodyPoseMatchSetupUtil
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class BodyPoseMatchSetupUtil
{
    public void AdjustAvatarScaleByNeck(Transform avatarRoot, Dictionary<HumanBodyBones, HashSet<Transform>> humanBoneMap, float targetHeight)
    {
        if (avatarRoot == null)
        {
            Debug.LogWarning("[AvatarBodyMatchUtil] NormalizeAvatarScaleByNeck: avatar == null");
            return;
        }
        Transform boneFromBoneMap = new BodyPoseMatch_CommonUtil().GetBoneFromBoneMap(humanBoneMap, HumanBodyBones.Neck);
        if (boneFromBoneMap == null)
        {
            Debug.LogWarning("[AvatarBodyMatchUtil] " + avatarRoot.name + " 에서 Neck 본을 찾지 못했습니다. 스케일 정규화를 건너뜁니다.");
            return;
        }
        Transform transform = avatarRoot.transform;
        float num = boneFromBoneMap.position.y - transform.position.y;
        if (Mathf.Approximately(num, 0f))
        {
            Debug.LogWarning($"[AvatarBodyMatchUtil] {avatarRoot.name} Neck Y가 0에 가까워 스케일 계산을 건너뜁니다. (neckY = {num})");
            return;
        }
        float num2 = targetHeight / num;
        Vector3 localScale = transform.localScale;
        localScale *= num2;
        transform.localScale = localScale;
    }

    public GameObject CreateBodyProxy(Animator sourceAvatar, IReadOnlyList<SkinnedMeshRenderer> sourceBodyMeshes, out List<SkinnedMeshRenderer> proxyBodyMeshes, out Dictionary<Transform, Transform> sourceToProxy)
    {
        proxyBodyMeshes = null;
        if (sourceAvatar == null)
        {
            Debug.LogError("[AvatarBodyMatchUtil] CreateSourceBodyProxy: sourceAvatar == null");
            sourceToProxy = new Dictionary<Transform, Transform>();
            return null;
        }
        GameObject clone = Object.Instantiate(sourceAvatar.gameObject);
        clone.name = sourceAvatar.name + "_BodyProxy";
        HashSet<Transform> remainTransforms = new HashSet<Transform>();
        remainTransforms.Add(clone.transform);
        Animator component = clone.GetComponent<Animator>();
        if (component != null)
        {
            component.enabled = false;
            remainTransforms.Add(component.transform);
        }
        if (component != null && component.avatar != null && component.avatar.isHuman)
        {
            for (int i = 0; i < 55; i++)
            {
                HumanBodyBones humanBoneId = (HumanBodyBones)i;
                Transform boneTransform = component.GetBoneTransform(humanBoneId);
                if (boneTransform != null)
                {
                    remainTransforms.Add(boneTransform);
                }
            }
        }
        HashSet<Mesh> hashSet = new HashSet<Mesh>();
        if (sourceBodyMeshes != null)
        {
            foreach (SkinnedMeshRenderer sourceBodyMesh in sourceBodyMeshes)
            {
                if (!(sourceBodyMesh == null) && !(sourceBodyMesh.sharedMesh == null))
                {
                    hashSet.Add(sourceBodyMesh.sharedMesh);
                }
            }
        }
        SkinnedMeshRenderer[] componentsInChildren = clone.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
        List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
        SkinnedMeshRenderer[] array = componentsInChildren;
        foreach (SkinnedMeshRenderer skinnedMeshRenderer in array)
        {
            if (!(skinnedMeshRenderer == null))
            {
                Mesh sharedMesh = skinnedMeshRenderer.sharedMesh;
                if (!(sharedMesh == null) && hashSet.Contains(sharedMesh))
                {
                    list.Add(skinnedMeshRenderer);
                }
            }
        }
        if (list.Count == 0)
        {
            Debug.LogWarning("[AvatarBodyMatchUtil] CreateSourceBodyProxy: clone에서 동일 sharedMesh를 가진 BodyMesh를 찾지 못했습니다.");
        }
        if (list.Count > 0)
        {
            MeshClassifier meshClassifier = new MeshClassifier();
            foreach (SkinnedMeshRenderer item in list)
            {
                if (item == null)
                {
                    continue;
                }
                remainTransforms.Add(item.transform);
                HashSet<Transform> activeBones = meshClassifier.GetActiveBones(item);
                if (activeBones == null)
                {
                    Debug.LogWarning("[AvatarBodyMatchUtil] CreateSourceBodyProxy: clone smr '" + item.name + "' has null bones array (mesh='" + item.sharedMesh?.name + "')");
                    continue;
                }
                foreach (Transform item2 in activeBones)
                {
                    if (!(item2 == null))
                    {
                        remainTransforms.Add(item2);
                    }
                }
            }
        }
        foreach (Transform item3 in remainTransforms.ToList())
        {
            AddWithParents(item3);
        }
        Transform[] componentsInChildren2 = clone.GetComponentsInChildren<Transform>(includeInactive: true);
        for (int num = componentsInChildren2.Length - 1; num >= 0; num--)
        {
            Transform transform = componentsInChildren2[num];
            if (!(transform == null) && !(transform == clone.transform) && !remainTransforms.Contains(transform))
            {
                Object.DestroyImmediate(transform.gameObject);
            }
        }
        proxyBodyMeshes = list;
        new BoneMatchUtil().BuildSourceToProxyBoneMap(sourceAvatar, component, out sourceToProxy);
        return clone;
        void AddWithParents(Transform t)
        {
            while (t != null && t != clone.transform)
            {
                remainTransforms.Add(t);
                t = t.parent;
            }
        }
    }

    public Vector3 GetComprehensiveScale(Transform rootT, Dictionary<HumanBodyBones, HashSet<Transform>> clothHumanoidBoneMap, ProfileData profileData)
    {
        if (rootT == null)
        {
            throw new AutoMorpherException("Root Transform is Missing", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - rootT is null");
        }
        if (profileData.bones == null || profileData.bones.Count == 0)
        {
            throw new AutoMorpherException("Profile Bones are Missing", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - profileData.bones is null or empty");
        }
        Transform transform = null;
        if (clothHumanoidBoneMap.TryGetValue(HumanBodyBones.Hips, out var value) && value != null && value.Count > 0)
        {
            foreach (Transform item in value)
            {
                if (item != null)
                {
                    transform = item;
                    break;
                }
            }
        }
        if (transform == null)
        {
            throw new AutoMorpherException("Hip Transform is Missing", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - failed to get [hip] transform from clothHumanoidBoneMap");
        }
        BoneData boneData = null;
        for (int i = 0; i < profileData.bones.Count; i++)
        {
            BoneData boneData2 = profileData.bones[i];
            if (boneData2 != null && boneData2.hBone == HumanBodyBones.Hips)
            {
                boneData = boneData2;
                break;
            }
        }
        if (boneData == null)
        {
            throw new AutoMorpherException("Hip Bone Data is Missing in Profile", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - profileData bones does not contain Hips");
        }
        Vector3 rootLocalScale = boneData.rootLocalScale;
        Vector3 lossyScale = rootT.lossyScale;
        Vector3 lossyScale2 = transform.lossyScale;
        Vector3 vector = new Vector3(lossyScale2.x / lossyScale.x, lossyScale2.y / lossyScale.y, lossyScale2.z / lossyScale.z);
        return new Vector3(vector.x / rootLocalScale.x, vector.y / rootLocalScale.y, vector.z / rootLocalScale.z);
    }
}
