using UnityEditor;
using Unity.MLAgents.Editor;
using Unity.MLAgents.Extensions.Sensors;

namespace Unity.MLAgents.Extensions.Editor
{
    [CustomEditor(typeof(RigidBodySensorComponent))]
    [CanEditMultipleObjects]
    internal class RigidBodySensorComponentEditor : UnityEditor.Editor
    {
        bool ShowHierarchy = true;

        public override void OnInspectorGUI()
        {
            var so = serializedObject;
            so.Update();

            var rbSensorComp = so.targetObject as RigidBodySensorComponent;
            if (rbSensorComp.IsTrivial())
            {
                EditorGUILayout.HelpBox(
                    "The Root Body has no Joints, and the Virtual Root is null or the same as the " +
                    "Root Body's GameObject. This will not generate any useful observations; they will always " +
                    "be the identity values. Consider removing this component since it won't help the Agent.",
                    MessageType.Warning
                );
            }

            bool requireExtractorUpdate;

            EditorGUI.BeginDisabledGroup(!EditorUtilities.CanUpdateModelProperties());
            {
                // All the fields affect the sensor order or observation size,
                // So can't be changed at runtime.
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(so.FindProperty("RootBody"), true);
                EditorGUILayout.PropertyField(so.FindProperty("VirtualRoot"), true);

                // Changing the root body or virtual root changes the hierarchy, so we need to reset later.
                requireExtractorUpdate = EditorGUI.EndChangeCheck();

                EditorGUILayout.PropertyField(so.FindProperty("Settings"), true);

                // Collapsible tree for the body hierarchy
                ShowHierarchy = EditorGUILayout.Foldout(ShowHierarchy, "Hierarchy", true);
                if (ShowHierarchy)
                {
                    var treeNodes = rbSensorComp.GetDisplayNodes();
                    var originalIndent = EditorGUI.indentLevel;
                    foreach (var node in treeNodes)
                    {
                        var obj = node.NodeObject;
                        var objContents = EditorGUIUtility.ObjectContent(obj, obj.GetType());
                        EditorGUI.indentLevel = originalIndent + node.Depth;
                        var enabled = EditorGUILayout.Toggle(objContents, node.Enabled);
                        rbSensorComp.SetPoseEnabled(node.OriginalIndex, enabled);
                    }

                    EditorGUI.indentLevel = originalIndent;
                }

                EditorGUILayout.PropertyField(so.FindProperty("sensorName"), true);
            }
            EditorGUI.EndDisabledGroup();

            so.ApplyModifiedProperties();
            if (requireExtractorUpdate)
            {
                rbSensorComp.ResetPoseExtractor();
            }
        }
    }
}
