using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using KindRetargeting;

public class RetargetingControlWindow : EditorWindow
{
    private Vector2 scrollPosition;
    private bool showGlobalSettings = true;
    private CustomRetargetingScript[] retargetingScripts;

    private Dictionary<string, RetargetingPreset> presets = new Dictionary<string, RetargetingPreset>();
    private string currentPresetName = "";

    // 각 객체별 foldout 상태를 저장할 Dictionary들
    private Dictionary<int, bool> weightSettingsFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> hipsSettingsFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> kneeSettingsFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> fingerControlFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> fingerCopyFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> motionSettingsFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> floorSettingsFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> scaleSettingsFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> leftHandFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> rightHandFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> headFoldouts = new Dictionary<int, bool>();
    private Dictionary<int, bool> propControlFoldouts = new Dictionary<int, bool>();

    private bool isDirty = false;
    private double lastUpdateTime;
    private const double UPDATE_INTERVAL = 0.25; // 250ms
    private const float SLIDER_HEIGHT = 100f;
    private const float SLIDER_WIDTH = 25f;
    private const float SPACING = 5f;

    [MenuItem("Tools/리타게팅 컨트롤 패널")]
    public static void ShowWindow()
    {
        GetWindow<RetargetingControlWindow>("리타게팅 컨트롤");
    }

    private void OnEnable()
    {
        // 씬에서 모든 리타게팅 스크립트 찾기
        retargetingScripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
        EditorApplication.update += OnEditorUpdate;
        Undo.undoRedoPerformed += OnUndoRedo;
        lastUpdateTime = EditorApplication.timeSinceStartup;
    }

    private void OnDisable()
    {
        EditorApplication.update -= OnEditorUpdate;
        Undo.undoRedoPerformed -= OnUndoRedo;
    }

    private void OnEditorUpdate()
    {
        // 플레이 모드일 때는 업데이트 처리를 하지 않음
        if (Application.isPlaying)
            return;

        // 업데이트 간격을 더 길게 조정 (100ms -> 250ms)
        if (EditorApplication.timeSinceStartup - lastUpdateTime < UPDATE_INTERVAL)
            return;

        // 실제로 변경된 경우에만 리프레시 수행
        if (isDirty)
        {
            RefreshScripts();
            isDirty = false;
            lastUpdateTime = EditorApplication.timeSinceStartup;
        }
    }

    private void OnUndoRedo()
    {
        isDirty = true;
        Repaint();
    }

    private void RefreshScripts()
    {
        // 플레이 모드일 때는 씬 수정을 하지 않음
        if (Application.isPlaying)
            return;

        // 캐싱된 스크립트 사용
        if (retargetingScripts == null || retargetingScripts.Length == 0)
            retargetingScripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);

        bool anyDirty = false;

        foreach (var script in retargetingScripts)
        {
            if (script != null && script.isActiveAndEnabled)  // 활성화된 컴포넌트만 처리
            {
                EditorUtility.SetDirty(script);
                anyDirty = true;
            }
        }

        if (anyDirty && !Application.isPlaying)  // 플레이 모드가 아닐 때만 씬을 수정
        {
            UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(
                retargetingScripts[0].gameObject.scene);
        }

        // 불필요한 리페인트 제거
        if (focusedWindow == this)
        {
            Repaint();
        }
    }

    private void OnGUI()
    {
        if (retargetingScripts == null || retargetingScripts.Length == 0)
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            EditorGUILayout.HelpBox("씬에서 리타게팅 스크립트를 찾을 수 없습니다.", MessageType.Warning);
            
            if (GUILayout.Button("리타게팅 스크립트 리프레시", GUILayout.Height(30)))
            {
                retargetingScripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
                
                // 각 리타게팅 스크립트에 대해 필요한 컴포넌트들 체크
                foreach (var script in retargetingScripts)
                {
                    if (script != null)
                    {
                        // LimbWeightController가 없다면 추가
                        if (script.GetComponent<LimbWeightController>() == null)
                        {
                            script.gameObject.AddComponent<LimbWeightController>();
                        }
                        
                        // FingerShapedController가 없다면 추가
                        if (script.GetComponent<FingerShapedController>() == null)
                        {
                            script.gameObject.AddComponent<FingerShapedController>();
                        }
                        
                        // PropLocationController가 없다면 추가
                        if (script.GetComponent<PropLocationController>() == null)
                        {
                            script.gameObject.AddComponent<PropLocationController>();
                        }
                        
                        EditorUtility.SetDirty(script.gameObject);
                    }
                }
                
                isDirty = true;
                Repaint();
            }
            
            EditorGUILayout.Space(5);
            EditorGUILayout.LabelField("마지막 리프레시: " + System.DateTime.Now.ToString("HH:mm:ss"), EditorStyles.miniLabel);
            
            EditorGUILayout.EndVertical();
            return;
        }

        // 전역 설정 옵션
        DrawGlobalSettings();

        EditorGUILayout.Space();

        // 개별 캐릭터 설정
        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
        var scripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
        foreach (var script in scripts)
        {
            DrawRetargetingControls(script);
        }
        EditorGUILayout.EndScrollView();
    }

    private void DrawGlobalSettings()
    {
        showGlobalSettings = EditorGUILayout.Foldout(showGlobalSettings, "전역 설정", true);
        if (showGlobalSettings)
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);

            // 전역 캘리브레이션 버튼
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("모든 캐릭터 I-포즈 캘리브레이션"))
            {
                var scripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
                foreach (var script in scripts)
                {
                    // I-포즈 캘리브레이션 로직
                }
                AssetDatabase.SaveAssets();
            }
            if (GUILayout.Button("모든 캐릭터 캘리브레이션 초기화"))
            {
                var scripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
                foreach (var script in scripts)
                {
                    script.ResetPoseAndCache();
                    EditorUtility.SetDirty(script);
                }
                AssetDatabase.SaveAssets();
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();
        }
    }

    private void DrawRetargetingControls(CustomRetargetingScript script)
    {
        if (script == null) return;

        int instanceID = script.GetInstanceID();

        // Dictionary 초기화
        if (!weightSettingsFoldouts.ContainsKey(instanceID)) weightSettingsFoldouts[instanceID] = false;
        if (!hipsSettingsFoldouts.ContainsKey(instanceID)) hipsSettingsFoldouts[instanceID] = false;
        if (!kneeSettingsFoldouts.ContainsKey(instanceID)) kneeSettingsFoldouts[instanceID] = false;
        if (!fingerControlFoldouts.ContainsKey(instanceID)) fingerControlFoldouts[instanceID] = false;
        if (!fingerCopyFoldouts.ContainsKey(instanceID)) fingerCopyFoldouts[instanceID] = false;
        if (!motionSettingsFoldouts.ContainsKey(instanceID)) motionSettingsFoldouts[instanceID] = false;
        if (!floorSettingsFoldouts.ContainsKey(instanceID)) floorSettingsFoldouts[instanceID] = false;
        if (!scaleSettingsFoldouts.ContainsKey(instanceID)) scaleSettingsFoldouts[instanceID] = false;
        if (!leftHandFoldouts.ContainsKey(instanceID)) leftHandFoldouts[instanceID] = false;
        if (!rightHandFoldouts.ContainsKey(instanceID)) rightHandFoldouts[instanceID] = false;
        if (!headFoldouts.ContainsKey(instanceID)) headFoldouts[instanceID] = false;
        if (!propControlFoldouts.ContainsKey(instanceID)) propControlFoldouts[instanceID] = false;

        SerializedObject serializedObject = new SerializedObject(script);

        // 시작 시 Update 호출
        serializedObject.Update();

        EditorGUI.BeginChangeCheck();

        EditorGUILayout.BeginVertical(EditorStyles.helpBox);

        // 헤더 부분
        DrawHeader(script);

        GUI.backgroundColor = new Color(0.8f, 0.9f, 1f);

        // 가중치 설정
        weightSettingsFoldouts[instanceID] = EditorGUILayout.Foldout(weightSettingsFoldouts[instanceID], "가중치 설정", true);
        if (weightSettingsFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawWeightSettings(script);
            EditorGUI.indentLevel--;
        }

        // 힙 설정
        hipsSettingsFoldouts[instanceID] = EditorGUILayout.Foldout(hipsSettingsFoldouts[instanceID], "힙 위치 보정", true);
        if (hipsSettingsFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            var hipsWeightProp = serializedObject.FindProperty("hipsWeight");
            EditorGUILayout.PropertyField(hipsWeightProp, new GUIContent("힙 가중치"));
            EditorGUI.indentLevel--;
        }

        // 무릎 설정
        kneeSettingsFoldouts[instanceID] = EditorGUILayout.Foldout(kneeSettingsFoldouts[instanceID], "무릎 위치 조정", true);
        if (kneeSettingsFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            var kneeFrontBackProp = serializedObject.FindProperty("kneeFrontBackWeight");
            var kneeInOutProp = serializedObject.FindProperty("kneeInOutWeight");

            EditorGUILayout.Slider(kneeFrontBackProp, -1f, 1f, new GUIContent("무릎 앞/뒤 가중치"));
            EditorGUILayout.Slider(kneeInOutProp, -1f, 1f, new GUIContent("무릎 안/밖 가중치"));
            EditorGUI.indentLevel--;
        }

        // 손가락 제어 설정
        fingerControlFoldouts[instanceID] = EditorGUILayout.Foldout(fingerControlFoldouts[instanceID], "손가락 제어 설정", true);
        if (fingerControlFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawFingerControls(script);
            EditorGUI.indentLevel--;
        }

        // 손가락 복제 설정
        fingerCopyFoldouts[instanceID] = EditorGUILayout.Foldout(fingerCopyFoldouts[instanceID], "손가락 복제 설정", true);
        if (fingerCopyFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawFingerCopySettings(script);
            EditorGUI.indentLevel--;
        }

        // 모션 설정
        motionSettingsFoldouts[instanceID] = EditorGUILayout.Foldout(motionSettingsFoldouts[instanceID], "모션 설정", true);
        if (motionSettingsFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawMotionSettings(serializedObject);
            EditorGUI.indentLevel--;
        }

        // 바닥 높이 설정 섹션
        floorSettingsFoldouts[instanceID] = EditorGUILayout.Foldout(floorSettingsFoldouts[instanceID], "바닥 높이 설정", true);
        if (floorSettingsFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawFloorSettings(serializedObject);
            EditorGUI.indentLevel--;
        }

        // 아바타 크기 설정 섹션
        scaleSettingsFoldouts[instanceID] = EditorGUILayout.Foldout(scaleSettingsFoldouts[instanceID], "아바타 크기 설정", true);
        if (scaleSettingsFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawScaleSettings(serializedObject);
            EditorGUI.indentLevel--;
        }

        // 프랍 컨트롤 설정
        propControlFoldouts[instanceID] = EditorGUILayout.Foldout(propControlFoldouts[instanceID], "프랍 설정", true);
        if (propControlFoldouts[instanceID])
        {
            EditorGUI.indentLevel++;
            DrawPropControls(script);
            EditorGUI.indentLevel--;
        }

        EditorGUILayout.EndVertical();

        // 캘리브레이션 설정
        EditorGUILayout.Space(10);
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        DrawCalibrationControls(script);
        EditorGUILayout.EndVertical();

        // 변경사항이 있을 경우 적용
        if (EditorGUI.EndChangeCheck())
        {
            // 수정된 속성 적용
            serializedObject.ApplyModifiedProperties();

            // 스크립트를 더티로 표시
            EditorUtility.SetDirty(script);

            // isDirty 플래그 설정
            isDirty = true;

            // 씬 뷰 갱신
            SceneView.RepaintAll();
        }
    }

    // 헤더 그리기 함수 (기존의 버튼 코드)
    private void DrawHeader(CustomRetargetingScript script)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField($"캐릭터: {script.gameObject.name}", EditorStyles.boldLabel);
        GUILayout.FlexibleSpace();

        var animator = script.GetComponent<Animator>();
        if (animator != null)
        {
            if (GUILayout.Button("전체", GUILayout.Width(50)))
            {
                Selection.activeGameObject = script.gameObject;
                if (SceneView.lastActiveSceneView != null)
                {
                    SceneView.lastActiveSceneView.FrameSelected();
                }
            }

            if (GUILayout.Button("머리", GUILayout.Width(50)))
            {
                var head = animator.GetBoneTransform(HumanBodyBones.Head);
                if (head != null)
                {
                    Selection.activeGameObject = head.gameObject;
                    if (SceneView.lastActiveSceneView != null)
                    {
                        SceneView.lastActiveSceneView.FrameSelected();
                    }
                }
            }

            if (GUILayout.Button("왼손", GUILayout.Width(50)))
            {
                var leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
                if (leftHand != null)
                {
                    Selection.activeGameObject = leftHand.gameObject;
                    if (SceneView.lastActiveSceneView != null)
                    {
                        SceneView.lastActiveSceneView.FrameSelected();
                    }
                }
            }

            if (GUILayout.Button("오른손", GUILayout.Width(50)))
            {
                var rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
                if (rightHand != null)
                {
                    Selection.activeGameObject = rightHand.gameObject;
                    if (SceneView.lastActiveSceneView != null)
                    {
                        SceneView.lastActiveSceneView.FrameSelected();
                    }
                }
            }
        }
        EditorGUILayout.EndHorizontal();
    }

    private void DrawCalibrationControls(CustomRetargetingScript script)
    {
        // 캘리브레이션 상태 표시
        EditorGUILayout.LabelField(script.HasCachedSettings() ?
            "캘리브레이션 데이터가 저장되어 있습니다." :
            "저장된 캘리브레이션 데이터가 없습니다.",
            EditorStyles.boldLabel);

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("I-포즈 캘리브레이션"))
        {
            script.I_PoseCalibration();
        }
        if (GUILayout.Button("캘리브레이션 초기화"))
        {
            script.ResetPoseAndCache();
        }
        EditorGUILayout.EndHorizontal();
    }

    private void ResetWeights(CustomRetargetingScript script)
    {
        var limb = script.GetComponent<LimbWeightController>();
        if (limb != null)
        {
            // 기본 설정값으로 초기화
            limb.maxDistance = 0.3f;
            limb.minDistance = 0.1f;
            limb.weightSmoothSpeed = 10f;
            limb.groundHipsMinHeight = 0.3f;
            limb.groundHipsMaxHeight = 0.7f;

            EditorUtility.SetDirty(limb);
        }
    }

    private void ResetAllSettings(CustomRetargetingScript script)
    {
        // 모든 컴포넌트의 설정을 기본값으로 초기화
        ResetWeights(script);
        script.ResetPoseAndCache();

        var shoulder = script.GetComponent<ShoulderCorrectionFunction>();
        if (shoulder != null)
        {
            shoulder.blendStrength = 2f;
            shoulder.maxHeightDifference = 0.3f;
            EditorUtility.SetDirty(shoulder);
        }
    }

    private void SavePreset()
    {
        if (string.IsNullOrEmpty(currentPresetName)) return;

        var preset = new RetargetingPreset();
        if (retargetingScripts.Length > 0)
        {
            var script = retargetingScripts[0];
            var shoulder = script.GetComponent<ShoulderCorrectionFunction>();
            var limb = script.GetComponent<LimbWeightController>();

            if (shoulder != null)
            {
                preset.shoulderBlendStrength = shoulder.blendStrength;
                preset.shoulderMaxHeightDiff = shoulder.maxHeightDifference;
            }

            if (limb != null)
            {
                preset.limbMaxDistance = limb.maxDistance;
                preset.limbMinDistance = limb.minDistance;
                preset.footHeightMinThreshold = limb.footHeightMinThreshold;
                preset.footHeightMaxThreshold = limb.footHeightMaxThreshold;
            }

            presets[currentPresetName] = preset;
            EditorUtility.SetDirty(this);
        }
    }

    private void LoadPreset()
    {
        if (!presets.TryGetValue(currentPresetName, out RetargetingPreset preset)) return;

        foreach (var script in retargetingScripts)
        {
            var shoulder = script.GetComponent<ShoulderCorrectionFunction>();
            var limb = script.GetComponent<LimbWeightController>();

            if (shoulder != null)
            {
                shoulder.blendStrength = preset.shoulderBlendStrength;
                shoulder.maxHeightDifference = preset.shoulderMaxHeightDiff;
            }

            if (limb != null)
            {
                limb.maxDistance = preset.limbMaxDistance;
                limb.minDistance = preset.limbMinDistance;
                limb.footHeightMinThreshold = preset.footHeightMinThreshold;
                limb.footHeightMaxThreshold = preset.footHeightMaxThreshold;
            }

            EditorUtility.SetDirty(script);
        }
    }

    private bool DrawHandControls(string label, string prefix, bool foldout, SerializedObject serializedController)
    {
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.BeginHorizontal(GUILayout.Width(200));
        bool newFoldout = EditorGUILayout.Foldout(foldout, label, true);

        SerializedProperty handEnabledProp = serializedController.FindProperty($"{prefix}HandEnabled");
        bool handEnabled = EditorGUILayout.Toggle("제어 활성화", handEnabledProp.boolValue);
        if (handEnabled != handEnabledProp.boolValue)
        {
            handEnabledProp.boolValue = handEnabled;
            if (handEnabled && !((FingerShapedController)serializedController.targetObject).enabled)
            {
                ((FingerShapedController)serializedController.targetObject).enabled = true;
            }
        }
        EditorGUILayout.EndHorizontal();

        if (GUILayout.Button("초기화", GUILayout.Width(60)))
        {
            ResetHandValues(prefix, serializedController);
        }
        EditorGUILayout.EndHorizontal();

        if (newFoldout && handEnabledProp.boolValue)
        {
            EditorGUILayout.Space(SPACING);
            DrawFingerSliders(prefix, serializedController);
            EditorGUILayout.Space(SPACING);
            DrawSpreadSlider(prefix, serializedController);
        }

        EditorGUILayout.EndVertical();

        return newFoldout;
    }

    private void DrawFingerControls(CustomRetargetingScript script)
    {
        var fingerController = script.GetComponent<FingerShapedController>();
        if (fingerController == null)
        {
            EditorGUILayout.HelpBox("FingerShapedController가 없습니다.", MessageType.Warning);
            if (GUILayout.Button("FingerShapedController 추가"))
            {
                fingerController = script.gameObject.AddComponent<FingerShapedController>();
                EditorUtility.SetDirty(script.gameObject);
            }
            return;
        }

        SerializedObject serializedController = new SerializedObject(fingerController);
        serializedController.Update();

        // 활성화/비활성화 토글
        EditorGUI.BeginChangeCheck();
        bool isEnabled = EditorGUILayout.Toggle("손가락 제어 활성화", fingerController.enabled);
        if (EditorGUI.EndChangeCheck())
        {
            fingerController.enabled = isEnabled;
            EditorUtility.SetDirty(fingerController);
        }

        if (!fingerController.enabled) return;

        int instanceID = fingerController.GetInstanceID();

        // Dictionary 초기화 확인
        if (!leftHandFoldouts.ContainsKey(instanceID))
            leftHandFoldouts[instanceID] = true;
        if (!rightHandFoldouts.ContainsKey(instanceID))
            rightHandFoldouts[instanceID] = true;

        EditorGUILayout.BeginVertical(EditorStyles.helpBox);

        // 왼손 컨트롤
        leftHandFoldouts[instanceID] = DrawHandControls("왼손", "left", leftHandFoldouts[instanceID], serializedController);
        EditorGUILayout.Space(SPACING);

        // 오른손 컨트롤
        rightHandFoldouts[instanceID] = DrawHandControls("오른손", "right", rightHandFoldouts[instanceID], serializedController);
        EditorGUILayout.Space(SPACING);

        // 프리셋 버튼들
        DrawFingerPresetButtons(fingerController);

        EditorGUILayout.EndVertical();

        serializedController.ApplyModifiedProperties();
    }

    private void DrawFingerCopySettings(CustomRetargetingScript script)
    {
        if (script == null) return;

        SerializedObject serializedObject = new SerializedObject(script);
        serializedObject.Update();

        EditorGUILayout.BeginVertical(EditorStyles.helpBox);

        // CustomRetargetingScript의 fingerCopyMode 설정을 표시
        var fingerCopyModeProp = serializedObject.FindProperty("fingerCopyMode");
        if (fingerCopyModeProp != null)
        {
            EditorGUILayout.PropertyField(fingerCopyModeProp, new GUIContent("복제 방식", "손가락 포즈를 복제하는 방식을 선택합니다."));
            if (GUI.changed)
            {
                serializedObject.ApplyModifiedProperties();
                EditorUtility.SetDirty(script);
            }
        }
        else
        {
            EditorGUILayout.HelpBox("fingerCopyMode 프로퍼티를 찾을 수 없습니다.", MessageType.Warning);
        }

        EditorGUILayout.EndVertical();
    }

    private void DrawFingerSliders(string prefix, SerializedObject serializedController)
    {
        string[] fingerNames = { "Thumb", "Index", "Middle", "Ring", "Pinky" };
        float totalWidth = (SLIDER_WIDTH + SPACING) * fingerNames.Length;

        EditorGUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        EditorGUILayout.BeginHorizontal(GUILayout.Width(totalWidth));

        for (int i = 0; i < fingerNames.Length; i++)
        {
            EditorGUILayout.BeginVertical(GUILayout.Width(SLIDER_WIDTH));

            // 손가락 이름
            GUILayout.Label(GetKoreanFingerName(fingerNames[i]),
                EditorStyles.centeredGreyMiniLabel,
                GUILayout.Width(SLIDER_WIDTH));

            // 값 표시
            SerializedProperty prop = serializedController.FindProperty($"{prefix}{fingerNames[i]}Curl");
            GUILayout.Label(prop.floatValue.ToString("F1"),
                EditorStyles.centeredGreyMiniLabel,
                GUILayout.Width(SLIDER_WIDTH));

            // 세로 슬라이더를 중앙에 배치
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            prop.floatValue = GUILayout.VerticalSlider(
                prop.floatValue,
                1f,
                -1f,
                GUILayout.Width(SLIDER_WIDTH),
                GUILayout.Height(SLIDER_HEIGHT)
            );
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();

            if (i < fingerNames.Length - 1)
                GUILayout.Space(SPACING);
        }

        EditorGUILayout.EndHorizontal();
        GUILayout.FlexibleSpace();
        EditorGUILayout.EndHorizontal();
    }

    private string GetKoreanFingerName(string englishName)
    {
        switch (englishName)
        {
            case "Thumb": return "엄지";
            case "Index": return "검지";
            case "Middle": return "중지";
            case "Ring": return "약지";
            case "Pinky": return "새끼";
            default: return englishName;
        }
    }

    private void DrawSpreadSlider(string prefix, SerializedObject serializedController)
    {
        SerializedProperty spreadProp = serializedController.FindProperty($"{prefix}SpreadFingers");
        EditorGUILayout.BeginHorizontal();
        GUILayout.Space(15);
        EditorGUILayout.LabelField("벌리기", GUILayout.Width(50));
        spreadProp.floatValue = EditorGUILayout.Slider(spreadProp.floatValue, -1f, 1f);
        GUILayout.Space(15);
        EditorGUILayout.EndHorizontal();
    }

    private void DrawFingerPresetButtons(FingerShapedController controller)
    {
        EditorGUILayout.LabelField("손 모양 프리셋", EditorStyles.boldLabel);

        string[,] presets = {
            {"가위", "바위", "보"},
            {"브이", "검지", "초기화"}
        };

        for (int row = 0; row < 2; row++)
        {
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            for (int col = 0; col < 3; col++)
            {
                if (GUILayout.Button(presets[row, col], GUILayout.Height(30), GUILayout.Width(100)))
                {
                    ApplyPreset(controller, presets[row, col]);
                }

                if (col < 2)
                {
                    GUILayout.Space(10);
                }
            }

            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            if (row < 1)
            {
                GUILayout.Space(5);
            }
        }
    }

    private void ResetHandValues(string prefix, SerializedObject serializedController)
    {
        string[] props = { "ThumbCurl", "IndexCurl", "MiddleCurl", "RingCurl", "PinkyCurl", "SpreadFingers" };
        foreach (var prop in props)
        {
            serializedController.FindProperty($"{prefix}{prop}").floatValue = 0f;
        }
        serializedController.ApplyModifiedProperties();
    }

    private void ApplyPreset(FingerShapedController controller, string presetName)
    {
        // 프리셋 적용 시 양손 모두 활성화
        if (!controller.enabled)
        {
            controller.enabled = true;
        }

        switch (presetName)
        {
            case "가위":
                SetPreset(controller, 1f, 1f, -1f, -1f, -1f, 0.3f);
                break;
            case "바위":
                SetPreset(controller, -1f, -1f, -1f, -1f, -1f, 0f);
                break;
            case "보":
                SetPreset(controller, 1f, 1f, 1f, 1f, 1f, 1f);
                break;
            case "브이":
                SetPreset(controller, -1f, 1f, 1f, -1f, -1f, 1f);
                break;
            case "검지":
                SetPreset(controller, -1f, 1f, -1f, -1f, -1f, 0f);
                break;
            case "초기화":
                SetPreset(controller, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f);
                break;
        }
    }

    private void SetPreset(FingerShapedController controller, float thumb, float index,
        float middle, float ring, float pinky, float spread)
    {
        if (controller.leftHandEnabled)
        {
            controller.leftThumbCurl = thumb;
            controller.leftIndexCurl = index;
            controller.leftMiddleCurl = middle;
            controller.leftRingCurl = ring;
            controller.leftPinkyCurl = pinky;
            controller.leftSpreadFingers = spread;
        }

        if (controller.rightHandEnabled)
        {
            controller.rightThumbCurl = thumb;
            controller.rightIndexCurl = index;
            controller.rightMiddleCurl = middle;
            controller.rightRingCurl = ring;
            controller.rightPinkyCurl = pinky;
            controller.rightSpreadFingers = spread;
        }

        EditorUtility.SetDirty(controller);
    }

    private void DrawFingerSettings(SerializedObject serializedObject)
    {
        var fingerCopyModeProp = serializedObject.FindProperty("fingerCopyMode");
        var useFingerRoughProp = serializedObject.FindProperty("useFingerRoughMotion");
        var fingerRoughnessProp = serializedObject.FindProperty("fingerRoughness");

        EditorGUILayout.PropertyField(fingerCopyModeProp, new GUIContent("복제 방식"));
        EditorGUILayout.PropertyField(useFingerRoughProp, new GUIContent("러프 모션 사용"));
        if (useFingerRoughProp.boolValue)
        {
            EditorGUILayout.PropertyField(fingerRoughnessProp, new GUIContent("러프니스"));
        }
    }

    private void DrawMotionSettings(SerializedObject serializedObject)
    {
        serializedObject.Update();

        var useMotionFilterProp = serializedObject.FindProperty("useMotionFilter");
        var filterBufferSizeProp = serializedObject.FindProperty("filterBufferSize");
        var useBodyRoughProp = serializedObject.FindProperty("useBodyRoughMotion");
        var bodyRoughnessProp = serializedObject.FindProperty("bodyRoughness");

        EditorGUI.BeginChangeCheck();

        EditorGUILayout.PropertyField(useMotionFilterProp, new GUIContent("모션 필터 사용"));
        if (useMotionFilterProp.boolValue)
        {
            EditorGUILayout.PropertyField(filterBufferSizeProp, new GUIContent("필터 버퍼 크기"));
        }
        EditorGUILayout.PropertyField(useBodyRoughProp, new GUIContent("몸 러프 모션 사용"));
        if (useBodyRoughProp.boolValue)
        {
            EditorGUILayout.PropertyField(bodyRoughnessProp, new GUIContent("몸 러프니스"));
        }

        if (EditorGUI.EndChangeCheck())
        {
            serializedObject.ApplyModifiedProperties();
            EditorUtility.SetDirty(serializedObject.targetObject);
            SceneView.RepaintAll();
        }
    }

    private void DrawWeightSettings(CustomRetargetingScript script)
    {
        var limb = script.GetComponent<LimbWeightController>();
        if (limb != null)
        {
            var serializedLimb = new SerializedObject(limb);
            serializedLimb.Update();

            EditorGUI.BeginChangeCheck();

            // 거리 기반 가중치 설정
            EditorGUILayout.LabelField("손과 프랍과의 범위 (가중치 1 -> 0)");
            EditorGUILayout.BeginHorizontal();
            var minDistance = serializedLimb.FindProperty("minDistance");
            var maxDistance = serializedLimb.FindProperty("maxDistance");
            float minVal = minDistance.floatValue;
            float maxVal = maxDistance.floatValue;

            minVal = EditorGUILayout.FloatField(minVal, GUILayout.Width(50));
            EditorGUILayout.MinMaxSlider(ref minVal, ref maxVal, 0f, 1f);
            maxVal = EditorGUILayout.FloatField(maxVal, GUILayout.Width(50));

            minDistance.floatValue = minVal;
            maxDistance.floatValue = maxVal;
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(5);

            // 허리 거리 범위 설정
            EditorGUILayout.LabelField("의자와 허리 거리 범위(가중치 1 -> 0)");
            EditorGUILayout.BeginHorizontal();
            var hipsMinDistance = serializedLimb.FindProperty("hipsMinDistance");
            var hipsMaxDistance = serializedLimb.FindProperty("hipsMaxDistance");
            float hipsMin = hipsMinDistance.floatValue;
            float hipsMax = hipsMaxDistance.floatValue;

            hipsMin = EditorGUILayout.FloatField(hipsMin, GUILayout.Width(50));
            EditorGUILayout.MinMaxSlider(ref hipsMin, ref hipsMax, 0f, 1f);
            hipsMax = EditorGUILayout.FloatField(hipsMax, GUILayout.Width(50));

            hipsMinDistance.floatValue = hipsMin;
            hipsMaxDistance.floatValue = hipsMax;
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(5);

            // 바닥 기준 히프 높이 범위
            EditorGUILayout.LabelField("바닥과 허리 높이에 의한 블렌딩 (가중치 0 -> 1)");
            EditorGUILayout.BeginHorizontal();
            var groundHipsMin = serializedLimb.FindProperty("groundHipsMinHeight");
            var groundHipsMax = serializedLimb.FindProperty("groundHipsMaxHeight");
            float groundMin = groundHipsMin.floatValue;
            float groundMax = groundHipsMax.floatValue;

            groundMin = EditorGUILayout.FloatField(groundMin, GUILayout.Width(50));
            EditorGUILayout.MinMaxSlider(ref groundMin, ref groundMax, 0f, 2f);
            groundMax = EditorGUILayout.FloatField(groundMax, GUILayout.Width(50));

            groundHipsMin.floatValue = groundMin;
            groundHipsMax.floatValue = groundMax;
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(5);

            // 발 높이 기반 가중치 설정 추가
            EditorGUILayout.LabelField("지면으로부터 발의 범위에 의한 IK 블렌딩 (가중치 1 -> 0)");
            EditorGUILayout.BeginHorizontal();
            var footHeightMin = serializedLimb.FindProperty("footHeightMinThreshold");
            var footHeightMax = serializedLimb.FindProperty("footHeightMaxThreshold");
            float footMin = footHeightMin.floatValue;
            float footMax = footHeightMax.floatValue;

            footMin = EditorGUILayout.FloatField(footMin, GUILayout.Width(50));
            EditorGUILayout.MinMaxSlider(ref footMin, ref footMax, 0.1f, 1f);
            footMax = EditorGUILayout.FloatField(footMax, GUILayout.Width(50));

            footHeightMin.floatValue = footMin;
            footHeightMax.floatValue = footMax;
            EditorGUILayout.EndHorizontal();

            // 가중치 보간 설정
            var weightSmoothSpeed = serializedLimb.FindProperty("weightSmoothSpeed");
            EditorGUILayout.PropertyField(weightSmoothSpeed, new GUIContent("가중치 변화 속도"));

            if (EditorGUI.EndChangeCheck())
            {
                serializedLimb.ApplyModifiedProperties();
                EditorUtility.SetDirty(limb);
                SceneView.RepaintAll();
            }
        }
    }

    // 바닥 높이 설정 그리기 함수
    private void DrawFloorSettings(SerializedObject serializedObject)
    {
        EditorGUI.BeginChangeCheck();

        var floorHeightProp = serializedObject.FindProperty("floorHeight");
        EditorGUILayout.PropertyField(floorHeightProp, new GUIContent("바닥 높이 (-1 ~ 1)"));

        if (EditorGUI.EndChangeCheck())
        {
            serializedObject.ApplyModifiedProperties();
        }
    }

    // 크기 설정 UI 그리기 함수
    private void DrawScaleSettings(SerializedObject serializedObject)
    {
        EditorGUI.BeginChangeCheck();

        var avatarScaleProp = serializedObject.FindProperty("avatarScale");
        EditorGUILayout.PropertyField(avatarScaleProp, new GUIContent("아바타 크기"));

        if (EditorGUI.EndChangeCheck())
        {
            serializedObject.ApplyModifiedProperties();
        }
    }

    // 창이 포커스를 얻거나 잃을 때 리페인트
    private void OnFocus()
    {
        Repaint();
    }

    private void OnLostFocus()
    {
        Repaint();
    }

    // 에디터 업데이트 시 리페인트
    private void OnInspectorUpdate()
    {
        Repaint();
    }

    private void DrawPropControls(CustomRetargetingScript script)
    {
        var propController = script.GetComponent<PropLocationController>();
        if (propController == null)
        {
            EditorGUILayout.HelpBox("PropLocationController가 없습니다.", MessageType.Warning);
            if (GUILayout.Button("PropLocationController 추가"))
            {
                propController = script.gameObject.AddComponent<PropLocationController>();
                EditorUtility.SetDirty(script.gameObject);
            }
            return;
        }

        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        EditorGUILayout.LabelField("오프셋 조정", EditorStyles.boldLabel);

        // 왼손 오프셋
        Transform leftOffset = propController.GetLeftHandOffset();
        if (leftOffset != null)
        {
            bool showLeftHand = EditorGUILayout.Foldout(leftHandFoldouts.ContainsKey(script.GetInstanceID()) ?
                leftHandFoldouts[script.GetInstanceID()] : true, "왼손 오프셋");
            leftHandFoldouts[script.GetInstanceID()] = showLeftHand;

            if (showLeftHand)
            {
                EditorGUI.indentLevel++;
                EditorGUI.BeginChangeCheck();
                Vector3 leftPos = EditorGUILayout.Vector3Field("위치", leftOffset.localPosition);
                Vector3 leftRot = EditorGUILayout.Vector3Field("회전", leftOffset.localRotation.eulerAngles);

                if (EditorGUI.EndChangeCheck())
                {
                    Undo.RecordObject(leftOffset, "Update Left Hand Offset");
                    leftOffset.localPosition = leftPos;
                    leftOffset.localRotation = Quaternion.Euler(leftRot);
                    EditorUtility.SetDirty(leftOffset);
                }
                EditorGUI.indentLevel--;
            }
        }

        // 오른손 오프셋
        Transform rightOffset = propController.GetRightHandOffset();
        if (rightOffset != null)
        {
            bool showRightHand = EditorGUILayout.Foldout(rightHandFoldouts.ContainsKey(script.GetInstanceID()) ?
                rightHandFoldouts[script.GetInstanceID()] : true, "오른손 오프셋");
            rightHandFoldouts[script.GetInstanceID()] = showRightHand;

            if (showRightHand)
            {
                EditorGUI.indentLevel++;
                EditorGUI.BeginChangeCheck();
                Vector3 rightPos = EditorGUILayout.Vector3Field("위치", rightOffset.localPosition);
                Vector3 rightRot = EditorGUILayout.Vector3Field("회전", rightOffset.localRotation.eulerAngles);

                if (EditorGUI.EndChangeCheck())
                {
                    Undo.RecordObject(rightOffset, "Update Right Hand Offset");
                    rightOffset.localPosition = rightPos;
                    rightOffset.localRotation = Quaternion.Euler(rightRot);
                    EditorUtility.SetDirty(rightOffset);
                }
                EditorGUI.indentLevel--;
            }
        }

        // 머리 오프셋
        Transform headOffset = propController.GetHeadOffset();
        if (headOffset != null)
        {
            bool showHead = EditorGUILayout.Foldout(headFoldouts.ContainsKey(script.GetInstanceID()) ?
                headFoldouts[script.GetInstanceID()] : true, "머리 오프셋");
            headFoldouts[script.GetInstanceID()] = showHead;

            if (showHead)
            {
                EditorGUI.indentLevel++;
                EditorGUI.BeginChangeCheck();
                Vector3 headPos = EditorGUILayout.Vector3Field("위치", headOffset.localPosition);
                Vector3 headRot = EditorGUILayout.Vector3Field("회전", headOffset.localRotation.eulerAngles);

                if (EditorGUI.EndChangeCheck())
                {
                    Undo.RecordObject(headOffset, "Update Head Offset");
                    headOffset.localPosition = headPos;
                    headOffset.localRotation = Quaternion.Euler(headRot);
                    EditorUtility.SetDirty(headOffset);
                }
                EditorGUI.indentLevel--;
            }
        }

        // 프랍 목록
        EditorGUILayout.Space(10);
        EditorGUILayout.LabelField("부착된 프랍 목록", EditorStyles.boldLabel);

        // 머리 프랍
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("머리 프랍", EditorStyles.boldLabel);
        GameObject[] headProps = propController.GetHeadProps();
        DrawPropList(headProps);
        EditorGUILayout.EndVertical();

        // 왼손 프랍
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("왼손 프랍", EditorStyles.boldLabel);
        GameObject[] leftHandProps = propController.GetLeftHandProps();
        DrawPropList(leftHandProps);
        EditorGUILayout.EndVertical();

        // 오른손 프랍
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("오른손 프랍", EditorStyles.boldLabel);
        GameObject[] rightHandProps = propController.GetRightHandProps();
        DrawPropList(rightHandProps);
        EditorGUILayout.EndVertical();

        // 프랍 이동 버튼
        EditorGUILayout.Space();
        EditorGUILayout.LabelField("프랍 위치 이동", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("머리로 이동", GUILayout.Height(30)))
        {
            propController.MoveToHead();
        }
        if (GUILayout.Button("왼손으로 이동", GUILayout.Height(30)))
        {
            propController.MoveToLeftHand();
        }
        if (GUILayout.Button("오른손으로 이동", GUILayout.Height(30)))
        {
            propController.MoveToRightHand();
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        if (GUILayout.Button("프랍 해제", GUILayout.Height(30)))
        {
            Undo.RecordObject(Selection.activeGameObject?.transform, "Detach Prop");
            propController.DetachProp();
        }

        EditorGUILayout.EndVertical();
    }

    private void DrawPropList(GameObject[] props)
    {
        if (props.Length > 0)
        {
            foreach (GameObject prop in props)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField(prop.name);
                if (GUILayout.Button("선택", GUILayout.Width(60)))
                {
                    Selection.activeGameObject = prop;
                }
                EditorGUILayout.EndHorizontal();
            }
        }
        else
        {
            EditorGUILayout.LabelField("부착된 프랍 없음");
        }
    }
}

[System.Serializable]
public class RetargetingPreset
{
    public int ikIterations;
    public float ikDeltaThreshold;
    public float shoulderBlendStrength;
    public float shoulderMaxHeightDiff;
    public float limbMaxDistance;
    public float limbMinDistance;
    public float footHeightMinThreshold;
    public float footHeightMaxThreshold;
    // ... 기타 필요한 설정들
}