﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
using System;
using System.Linq;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
using Pumkin.AvatarTools;
using Pumkin.DataStructures;
using Pumkin.HelperFunctions;
using Pumkin.Presets;

namespace Pumkin.PoseEditor
{
    public class PumkinsPoseEditor
    {                
        static List<PumkinsPosePreset> _defaultPoses;
        public static List<PumkinsPosePreset> DefaultPoses
        {
            get
            {
                if(_defaultPoses == null || _defaultPoses.Count == 0)
                {
                    PumkinsPresetManager.CleanupPresetsOfType<PumkinsPosePreset>();
                    _defaultPoses = new List<PumkinsPosePreset>()
                    {
                        PumkinsPosePreset.CreatePreset("TPose", new float[]
                            {
                                -6.830189E-07f, 4.268869E-08f, 4.268868E-08f, -8.537737E-08f, 0f, 0f, 0f, 0f, 0f, 4.268868E-08f, 8.537737E-08f, 4.268868E-08f, 3.415095E-07f, 0f, 0f, 0f, 0f,
                                0f, 0f, 0f, 0f, 0.5994893f, 0.004985309f, 0.00297395f, 0.9989594f, -0.02284526f, -3.449878E-05f, -0.0015229f, -4.781132E-07f, 0.599489f, 0.004985378f, 0.002974245f,
                                0.9989589f, -0.02284535f, -3.548912E-05f, -0.001522672f, -1.024528E-07f, -2.429621E-07f, 1.549688E-07f, 0.3847253f, 0.310061f, -0.103543f, 0.9925866f, 0.159403f,
                                -0.01539368f, 0.01405432f, 5.680533E-08f, 2.701393E-07f, 0.3847259f, 0.3100605f, -0.1035404f, 0.9925874f, 0.1593992f, -0.01539393f, 0.01405326f, -0.7706841f, 0.423209f,
                                0.6456643f, 0.6362566f, 0.6677276f, -0.4597229f, 0.811684f, 0.8116837f, 0.6683907f, -0.5737826f, 0.8116839f, 0.8116843f, 0.6670681f, -0.6459302f, 0.8116837f, 0.8116839f,
                                0.666789f, -0.4676594f, 0.811684f, 0.8116839f, -0.7706831f, 0.4232127f, 0.6456538f, 0.6362569f, 0.6678051f, -0.4589976f, 0.8116843f, 0.8116842f, 0.668391f, -0.5737844f,
                                0.811684f, 0.8116837f, 0.6669571f, -0.6492739f, 0.8116841f, 0.8116843f, 0.6667888f, -0.4676568f, 0.8116842f, 0.8116836f,
                            }),
                        PumkinsPosePreset.CreatePreset("Idle", new float[]
                            {

                            }),
                    };
                }
                return _defaultPoses;
            }
        }
                
        static List<PumkinsPosePreset> humanPoses = new List<PumkinsPosePreset>();                
        
        public static void SetDefaultPoseByName(GameObject avatar, string poseName)
        {
            PumkinsPosePreset pose = DefaultPoses.Find(o => o.name.ToLower() == poseName.ToLower());

            if(poseName.ToLower() == "tpose")
                PumkinsAvatarTools.OnPoseWasChanged(PumkinsAvatarTools.PoseChangeType.Reset);            
            else
                PumkinsAvatarTools.OnPoseWasChanged(PumkinsAvatarTools.PoseChangeType.Normal);

            pose.ApplyPreset(avatar);
        }

        public static void SetTPose(GameObject avatar)
        {            
            //For some reason this doesn't behave the same as SetTPoseHardcoded
            //despite using the same values. TODO: Investigate this later.
            SetDefaultPoseByName(avatar, "tpose");
        }

        /// <summary>
        /// Sets hardcoded TPose.
        /// </summary>        
        public static void SetTPoseHardcoded(GameObject avatar)
        {
            Undo.RegisterFullObjectHierarchyUndo(avatar, "Set TPose");            
                        
            var anim = avatar.GetComponent<Animator>();

            if(anim && anim.avatar && anim.avatar.isHuman)
            {
                Vector3 pos = avatar.transform.position;
                Quaternion rot = avatar.transform.rotation;

                avatar.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

                var humanPoseHandler = new HumanPoseHandler(anim.avatar, avatar.transform);

                var humanPose = new HumanPose();
                humanPoseHandler.GetHumanPose(ref humanPose);

                //A long time ago CATS used to export avatars with a Armature scale of 100. This caused issues applying poses.
                //For now we'll just hardcode search for "Armature".
                //TODO: Find a better way to get the armature and check if it's scale could cause issues when tposing
                Transform armature = avatar.transform.Find("Armature");
                if(!(armature && armature.localScale == Vector3.one))
                {
                    if(humanPose.bodyPosition.y < 1 && !Mathf.Approximately(humanPose.bodyPosition.y, 1))
                    {
                        humanPose.bodyPosition.y = 1;
                        PumkinsAvatarTools.LogVerbose(Strings.PoseEditor.bodyPositionYTooSmall, LogType.Warning, humanPose.bodyPosition.y.ToString());
                    }
                }

                #region Hardcoded TPose Values
                humanPose.muscles[0] = -6.830189E-07f;
                humanPose.muscles[1] = 4.268869E-08f;
                humanPose.muscles[2] = 4.268868E-08f;
                humanPose.muscles[3] = -8.537737E-08f;
                humanPose.muscles[4] = 0f;
                humanPose.muscles[5] = 0f;
                humanPose.muscles[6] = 0f;
                humanPose.muscles[7] = 0f;
                humanPose.muscles[8] = 0f;
                humanPose.muscles[9] = 4.268868E-08f;
                humanPose.muscles[10] = -8.537737E-08f;
                humanPose.muscles[11] = 4.268868E-08f;
                humanPose.muscles[12] = 3.415095E-07f;
                humanPose.muscles[13] = 0f;
                humanPose.muscles[14] = 0f;
                humanPose.muscles[15] = 0f;
                humanPose.muscles[16] = 0f;
                humanPose.muscles[17] = 0f;
                humanPose.muscles[18] = 0f;
                humanPose.muscles[19] = 0f;
                humanPose.muscles[20] = 0f;
                humanPose.muscles[21] = 0.5994893f;
                humanPose.muscles[22] = 0.004985309f;
                humanPose.muscles[23] = 0.00297395f;
                humanPose.muscles[24] = 0.9989594f;
                humanPose.muscles[25] = -0.02284526f;
                humanPose.muscles[26] = -3.449878E-05f;
                humanPose.muscles[27] = -0.0015229f;
                humanPose.muscles[28] = -4.781132E-07f;
                humanPose.muscles[29] = 0.599489f;
                humanPose.muscles[30] = 0.004985378f;
                humanPose.muscles[31] = 0.002974245f;
                humanPose.muscles[32] = 0.9989589f;
                humanPose.muscles[33] = -0.02284535f;
                humanPose.muscles[34] = -3.548912E-05f;
                humanPose.muscles[35] = -0.001522672f;
                humanPose.muscles[36] = -1.024528E-07f;
                humanPose.muscles[37] = -2.429621E-07f;
                humanPose.muscles[38] = 1.549688E-07f;
                humanPose.muscles[39] = 0.3847253f;
                humanPose.muscles[40] = 0.310061f;
                humanPose.muscles[41] = -0.103543f;
                humanPose.muscles[42] = 0.9925866f;
                humanPose.muscles[43] = 0.159403f;
                humanPose.muscles[44] = -0.01539368f;
                humanPose.muscles[45] = 0.01405432f;
                humanPose.muscles[46] = 5.680533E-08f;
                humanPose.muscles[47] = 2.701393E-07f;
                humanPose.muscles[48] = 0.3847259f;
                humanPose.muscles[49] = 0.3100605f;
                humanPose.muscles[50] = -0.1035404f;
                humanPose.muscles[51] = 0.9925874f;
                humanPose.muscles[52] = 0.1593992f;
                humanPose.muscles[53] = -0.01539393f;
                humanPose.muscles[54] = 0.01405326f;
                humanPose.muscles[55] = -0.7706841f;
                humanPose.muscles[56] = 0.423209f;
                humanPose.muscles[57] = 0.6456643f;
                humanPose.muscles[58] = 0.6362566f;
                humanPose.muscles[59] = 0.6677276f;
                humanPose.muscles[60] = -0.4597229f;
                humanPose.muscles[61] = 0.811684f;
                humanPose.muscles[62] = 0.8116837f;
                humanPose.muscles[63] = 0.6683907f;
                humanPose.muscles[64] = -0.5737826f;
                humanPose.muscles[65] = 0.8116839f;
                humanPose.muscles[66] = 0.8116843f;
                humanPose.muscles[67] = 0.6670681f;
                humanPose.muscles[68] = -0.6459302f;
                humanPose.muscles[69] = 0.8116837f;
                humanPose.muscles[70] = 0.8116839f;
                humanPose.muscles[71] = 0.666789f;
                humanPose.muscles[72] = -0.4676594f;
                humanPose.muscles[73] = 0.811684f;
                humanPose.muscles[74] = 0.8116839f;
                humanPose.muscles[75] = -0.7706831f;
                humanPose.muscles[76] = 0.4232127f;
                humanPose.muscles[77] = 0.6456538f;
                humanPose.muscles[78] = 0.6362569f;
                humanPose.muscles[79] = 0.6678051f;
                humanPose.muscles[80] = -0.4589976f;
                humanPose.muscles[81] = 0.8116843f;
                humanPose.muscles[82] = 0.8116842f;
                humanPose.muscles[83] = 0.668391f;
                humanPose.muscles[84] = -0.5737844f;
                humanPose.muscles[85] = 0.811684f;
                humanPose.muscles[86] = 0.8116837f;
                humanPose.muscles[87] = 0.6669571f;
                humanPose.muscles[88] = -0.6492739f;
                humanPose.muscles[89] = 0.8116841f;
                humanPose.muscles[90] = 0.8116843f;
                humanPose.muscles[91] = 0.6667888f;
                humanPose.muscles[92] = -0.4676568f;
                humanPose.muscles[93] = 0.8116842f;
                humanPose.muscles[94] = 0.8116836f;
                #endregion

                humanPoseHandler.SetHumanPose(ref humanPose);
                avatar.transform.SetPositionAndRotation(pos, rot);

                PumkinsAvatarTools.OnPoseWasChanged(PumkinsAvatarTools.PoseChangeType.Reset);
            }
            else
            {
                PumkinsAvatarTools.Log(Strings.Log.cantSetPoseNonHumanoid, LogType.Warning, "TPose");
            }
        }

        void ApplyHumanPose(GameObject avatar, PumkinsPosePreset hp)
        {
            Undo.RegisterFullObjectHierarchyUndo(avatar, "Load Human Pose");

            Vector3 pos = avatar.transform.position;
            Quaternion rot = avatar.transform.rotation;
            avatar.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

            hp.ApplyPreset(avatar);
            PumkinsAvatarTools.OnPoseWasChanged(PumkinsAvatarTools.PoseChangeType.Normal);
            avatar.transform.SetPositionAndRotation(pos, rot);
        }
    }       
}