﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace FOHEART_Mocap
{
    public partial class FoheartGloveH1Pose : MonoBehaviour
    {
        public void FindAllSkeletons()
        {
            /*找到所有控制的骨骼本体*/
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsSkeleton32Index.NumOfBones; i++)
            {
                if (skeletonObjects[i] == null)
                {
                    skeletonObjects[i] = FindChildGameObject(gameObject, FoheartSkeletonName.mixAnimSkeletonNames[i]);
                }
                if (skeletonObjects[i] == null)
                {
                    skeletonObjects[i] = FindChildGameObject(gameObject, FoheartSkeletonName.steamVRSkeletonNames[i]);
                }
                if (skeletonObjects[i] == null)
                {
                    skeletonObjects[i] = FindChildGameObject(gameObject, FoheartSkeletonName.SK_MannequinSkeletonNames[i]);
                }
                if (skeletonObjects[i] == null)
                {
                    skeletonObjects[i] = FindChildGameObject(gameObject, FoheartSkeletonName.PlayerArmatureSkeletonNames[i]);
                }
                if (skeletonObjects[i] == null)
                {
                    skeletonObjects[i] = FindChildGameObject(gameObject, FoheartSkeletonName.RealTimeRascalsSkeletonNames[i]);
                }
                if (skeletonObjects[i] != null)
                {
                    skeletonTransforms[i] = skeletonObjects[i].transform;
                }
            }

            CheckDupSkeleton();

        }
        /*
         清除当前所有骨骼的绑定
        */
        public void ClearAllSkeletons()
        {
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsSkeleton32Index.NumOfBones; i++)
            {
                skeletonTransforms[i] = null;
            }
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsSkeleton32Index.NumOfBones; i++)
            {
                skeletonObjects[i] = null;
            }
        }

        public void FindAllEndPoints()
        {
            /*找到所有控制的骨骼本体*/
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsEndPoint12Index.NumOfBones; i++)
            {
                if (endPointObjects[i] == null)
                {
                    endPointObjects[i] = FindChildGameObject(gameObject, FoheartSkeletonName.SK_MannequinEndPointNames[i]);
                }

                if (endPointObjects[i] != null)
                {
                    endPointTransforms[i] = endPointObjects[i].transform;
                }
            }

        }
        public void ClearAllEndPoint()
        {
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsEndPoint12Index.NumOfBones; i++)
            {
                endPointTransforms[i] = null;
            }
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsEndPoint12Index.NumOfBones; i++)
            {
                endPointObjects[i] = null;
            }
        }

        /*检查重复骨骼*/
        public void CheckDupSkeleton()
        {
            Debug.Log(System.Reflection.MethodBase.GetCurrentMethod().Name);

            List<GameObject> lisA = new List<GameObject> { };
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsSkeleton32Index.NumOfBones; i++)
            {
                if (skeletonObjects[i] != null)
                {
                    lisA.Add(skeletonObjects[i]);
                }
            }
            //借助字典
            Dictionary<GameObject, int> dic = new Dictionary<GameObject, int>();
            lisA.ForEach(x =>
            {
                if (dic.ContainsKey(x))
                    dic[x] += 1;
                else
                    dic[x] = 0;
            });
            List<GameObject> lisDupValues = dic.Where(x => x.Value > 0).Select(x => x.Key).ToList();
            if (lisDupValues.Count != 0)
            {
                for (int i = 0; i < lisDupValues.Count; i++)
                {
                    Debug.LogWarning("[FOHEART_MOCAP]Duplicate skeleton binding:" + lisDupValues[i]);
                }
            }
            else
            {

            }
        }

        public void CheckDupEndPoint()
        {
            List<GameObject> lisA = new List<GameObject> { };
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsEndPoint12Index.NumOfBones; i++)
            {
                if (endPointObjects[i] != null)
                {
                    lisA.Add(endPointObjects[i]);
                }
            }
            //方式一 借助字典
            Dictionary<GameObject, int> dic = new Dictionary<GameObject, int>();
            lisA.ForEach(x =>
            {
                if (dic.ContainsKey(x))
                    dic[x] += 1;
                else
                    dic[x] = 0;
            });
            List<GameObject> lisDupValues = dic.Where(x => x.Value > 0).Select(x => x.Key).ToList();  //结果{"A"}
            if (lisDupValues.Count != 0)
            {
                for (int i = 0; i < lisDupValues.Count; i++)
                {
                    Debug.LogWarning("[FOHEART_MOCAP]Duplicate endpoint binding:" + lisDupValues[i]);
                }
            }
            else
            {

            }
        }

        public void LoadAllSkeletons()
        {
            Debug.Log(System.Reflection.MethodBase.GetCurrentMethod().Name);

            CheckDupSkeleton();
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsSkeleton32Index.NumOfBones; i++)
            {
                if (skeletonObjects[i] == null)
                    continue;

                skeletonTransforms[i] = skeletonObjects[i].transform;
            }
        }

        public void LoadAllEndPoint()
        {
            Debug.Log(System.Reflection.MethodBase.GetCurrentMethod().Name);

            CheckDupEndPoint();
            for (int i = 0; i < (int)FoheartSkeletonName.kinemHumanHandsEndPoint12Index.NumOfBones; i++)
            {
                if (endPointObjects[i] == null)
                    continue;

                endPointTransforms[i] = endPointObjects[i].transform;
            }
        }

        private void CaluateOrignalRot()
        {
          //  Debug.Log(System.Reflection.MethodBase.GetCurrentMethod().Name);

            orignalRots.Clear();
            orignalParentRots.Clear();
            // 记录骨骼节点原始旋转
            string boneOriEuler = "Ori EulerAngle:\r\n";
            for (int i = 0; i < skeletonTransforms.Length; i++)
            {
                Transform boneTrans = skeletonTransforms[i];
                if (boneTrans != null)
                {
                    Vector3 boneEulerRadius = boneTrans.rotation.eulerAngles;
                    Vector3 boneEulerRadiusLocalRotation = boneTrans.localRotation.eulerAngles;

                    Vector3 boneEulerDegreeGlobal = new Vector3(
                        (float)(boneEulerRadius.x),
                        (float)(boneEulerRadius.y),
                        (float)(boneEulerRadius.z)
                        );

                    Vector3 boneEulerDegreeLocal = new Vector3(
                     (float)(boneEulerRadiusLocalRotation.x),
                     (float)(boneEulerRadiusLocalRotation.y),
                     (float)(boneEulerRadiusLocalRotation.z)
                     );


                    if (frameProperties.printDebugLog)
                    {
                        /*输出模型原始所有骨骼的初始角度，全局坐标，相对于u3d世界坐标系*/

                        boneOriEuler += FoheartSkeletonName.kinemHumanSkeleton32[i].ToString();
                        boneOriEuler += ",";
                        boneOriEuler += boneEulerDegreeLocal.x.ToString();
                        boneOriEuler += ",";
                        boneOriEuler += boneEulerDegreeLocal.y.ToString();
                        boneOriEuler += ",";
                        boneOriEuler += boneEulerDegreeLocal.z.ToString();
                        boneOriEuler += "\r\n";
                    }
                }
                else
                {
                    boneOriEuler += FoheartSkeletonName.kinemHumanSkeleton32[i].ToString();
                    //boneOriEuler += "_null";
                    boneOriEuler += ",";
                    boneOriEuler += "0";
                    boneOriEuler += ",";
                    boneOriEuler += "0";
                    boneOriEuler += ",";
                    boneOriEuler += "0";
                    boneOriEuler += "\r\n";
                }
                orignalRots.Add(boneTrans == null ? Quaternion.identity : boneTrans.localRotation);
            }
            if (frameProperties.printDebugLog)
            {
                Debug.Log(boneOriEuler);
            }

            for (int i = 0; i < skeletonTransforms.Length; i++)
            {
                Transform boneTrans = skeletonTransforms[i];
                Quaternion parentQs = Quaternion.identity;
                if (boneTrans == null)
                {
                    orignalParentRots.Add(Quaternion.identity);
                    continue;
                }

                Transform tempParent = boneTrans.parent;

                while (tempParent != null)
                {
                    parentQs = tempParent.transform.localRotation * parentQs;
                    tempParent = tempParent.parent;
                    if (tempParent == null || tempParent == this.gameObject)
                    {
                        break;
                    }
                }
                orignalParentRots.Add(parentQs);

                Vector3 boneEulerRadius = parentQs.eulerAngles;
                Vector3 boneEulerDegree = new Vector3(
                    (float)(boneEulerRadius.x),
                    (float)(boneEulerRadius.y),
                   (float)(boneEulerRadius.z)
                    );
                if (frameProperties.printDebugLog)
                {
                    /*输出所有骨骼的初始角度，全局坐标，相对于u3d世界坐标系*/
                    // Debug.Log(kinemHumanSkeleton53[i] + " Parent EulerAngle:" + boneEulerDegree.x + "," + boneEulerDegree.y + "," + boneEulerDegree.z);
                }
            }
            // isOriginSkeletonAngleCalculated = true;
        }
    }
}
