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

public class BodyPoseMatch_Torso
{
    private readonly BodyPoseMatch_CommonUtil poseMatchCommonUtil;

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

    public void AlignTorsoByNeck(IReadOnlyCollection<Transform> sourceHipSet, Vector3 sourceNeckCenterWorld, Vector3 targetNeckCenterWorld)
    {
        if (sourceHipSet == null || sourceHipSet.Count == 0)
        {
            throw new AutoMorpherException("Source Hip Set is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - sourceHipSet is null or empty");
        }
        Transform transform = sourceHipSet.FirstOrDefault((Transform t) => t != null);
        if (transform == null)
        {
            throw new AutoMorpherException("Source Hip Transform is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - sourceHipSet has no valid Transform");
        }
        Vector3 lhs = targetNeckCenterWorld - sourceNeckCenterWorld;
        Vector3 forward = transform.forward;
        float num = Vector3.Dot(lhs, forward);
        Vector3 vector = forward * num;
        foreach (Transform item in sourceHipSet)
        {
            if (!(item == null))
            {
                item.position += vector;
            }
        }
    }

    public void AlignTorsoByNeck(GameObject proxyObject, IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, GameObject targetObject, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap)
    {
        if (proxyObject == null || targetObject == null)
        {
            throw new AutoMorpherException("Proxy/Target Object is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - proxyObject or targetObject is null");
        }
        RegionStats regionStats = this.ComputeNeckRegionStats(proxyObject.transform, proxyBakedBodyMeshes, proxyBoneMap);
        RegionStats regionStats2 = this.ComputeNeckRegionStats(targetObject.transform, targetBakedBodyMeshes, targetBoneMap);
        if (regionStats.length < 0.0001f || regionStats2.length < 0.0001f)
        {
            Debug.LogWarning("[BodyPoseMatch_Torso] AlignTorsoByNeck: Neck PCA 통계가 비정상입니다.");
            return;
        }
        if (proxyBoneMap == null || !proxyBoneMap.TryGetValue(HumanBodyBones.Hips, out var value) || value == null || value.Count == 0)
        {
            throw new AutoMorpherException("Proxy Hip Set is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - proxyBoneMap has no Hips bone set");
        }
        this.AlignTorsoByNeck(value, regionStats.center, regionStats2.center);
    }

    public void AlignTorsoByNeck(Transform targetTransform, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, Transform clothesTransform, ProfileData profileData, Vector3 comprehensiveScale)
    {
        if (targetTransform == null)
        {
            throw new AutoMorpherException("Target Transform is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - targetTransform is null");
        }
        if (profileData == null || profileData.NeckSpatialData == null)
        {
            throw new AutoMorpherException("Profile Neck Data is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - profileData or profileData.NeckSpatialData is null");
        }
        RegionStats regionStats = this.ComputeNeckRegionStats(targetTransform, targetBakedBodyMeshes, targetBoneMap);
        if (regionStats.length < 0.0001f)
        {
            Debug.LogWarning("[BodyPoseMatch_Torso] AlignTorsoByNeck: Neck PCA 통계가 비정상입니다.");
            return;
        }
        if (clothBoneMap == null || !clothBoneMap.TryGetValue(HumanBodyBones.Hips, out var value) || value == null || value.Count == 0)
        {
            throw new AutoMorpherException("Cloth Hip Set is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - clothBoneMap has no Hips bone set");
        }
        Vector3 profilePcaCenterWorld = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, profileData.NeckSpatialData, comprehensiveScale);
        this.AlignTorsoByNeck(value, profilePcaCenterWorld, regionStats.center);
    }

    public RegionStats ComputeNeckRegionStats(Transform avatarTransform, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap)
    {
        HumanBodyBones[] targetHumanBones = new HumanBodyBones[1] { HumanBodyBones.Neck };
        List<Vector3> list = this.poseMatchCommonUtil.CollectHumanoidVerticesWorld(targetHumanBones, avatarBakedBodyMeshes, avatarBoneMap);
        if (list == null || list.Count == 0)
        {
            Debug.LogWarning("[AvatarBodyMatchUtil] ComputeNeckRegionStats: neck vertices 0개. avatar=" + avatarTransform?.name);
            return default(RegionStats);
        }
        RegionStats result = new PcaUtil().ComputeRegionStats(list);
        Vector3 vector = avatarTransform.up;
        Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Head);
        Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.UpperChest);
        Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Chest);
        Transform boneFromBoneMap4 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Hips);
        Transform transform = ((boneFromBoneMap2 != null) ? boneFromBoneMap2 : boneFromBoneMap3);
        if (boneFromBoneMap != null && transform != null)
        {
            vector = boneFromBoneMap.position - transform.position;
        }
        else if (boneFromBoneMap != null && boneFromBoneMap4 != null)
        {
            vector = boneFromBoneMap.position - boneFromBoneMap4.position;
        }
        if (vector.sqrMagnitude > 1E-08f)
        {
            vector.Normalize();
        }
        if (Vector3.Dot(vector, avatarTransform.transform.up) < 0f)
        {
            vector = -vector;
        }
        result.principalAxis = vector;
        return result;
    }

    public void DrawTorsoPcaDebug(GameObject avatarObject, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, Color centerColor, Color axisColor, float axisScale = 1f, float duration = 0.1f)
    {
        if (!(avatarObject == null))
        {
            RegionStats regionStats = this.ComputeNeckRegionStats(avatarObject.transform, avatarBakedBodyMeshes, avatarBoneMap);
            if (regionStats.length < 0.0001f)
            {
                Debug.LogWarning($"[AvatarBodyMatchUtil] DrawNeckPcaDebug: neck.length가 너무 작음. avatar={avatarObject.name}, length={regionStats.length}");
                return;
            }
            Vector3 center = regionStats.center;
            Vector3 normalized = regionStats.principalAxis.normalized;
            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);
            float num2 = regionStats.length * 0.5f * axisScale;
            Vector3 end = center + normalized * num2;
            Debug.DrawLine(center, end, axisColor, duration);
            Debug.Log($"[AvatarBodyMatchUtil] DrawNeckPcaDebug: avatar={avatarObject.name}, center={center}, axis={normalized}, halfLen={num2}");
        }
    }
}
