using UnityEditor;
using UnityEngine;

namespace Jovian.EncounterSystem.Editor {
    /// <summary>Label list elements with the encounter id (fallback: name, then default).</summary>
    [CustomPropertyDrawer(typeof(Encounter))]
    public class EncounterDrawer : PropertyDrawer {
        private const string DefinitionBackingField = "<EncounterDefinition>k__BackingField";

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
            var displayLabel = ResolveLabel(property, label);

            var foldoutRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
            property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, displayLabel, true);

            if(!property.isExpanded) {
                return;
            }

            EditorGUI.indentLevel++;
            var y = position.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
            var iterator = property.Copy();
            var end = iterator.GetEndProperty();
            if(iterator.NextVisible(true)) {
                while(!SerializedProperty.EqualContents(iterator, end)) {
                    var h = EditorGUI.GetPropertyHeight(iterator, true);
                    var r = new Rect(position.x, y, position.width, h);
                    EditorGUI.PropertyField(r, iterator, true);
                    y += h + EditorGUIUtility.standardVerticalSpacing;
                    if(!iterator.NextVisible(false)) {
                        break;
                    }
                }
            }
            EditorGUI.indentLevel--;
        }

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
            var height = EditorGUIUtility.singleLineHeight;
            if(!property.isExpanded) {
                return height;
            }

            var iterator = property.Copy();
            var end = iterator.GetEndProperty();
            if(iterator.NextVisible(true)) {
                while(!SerializedProperty.EqualContents(iterator, end)) {
                    height += EditorGUI.GetPropertyHeight(iterator, true) + EditorGUIUtility.standardVerticalSpacing;
                    if(!iterator.NextVisible(false)) {
                        break;
                    }
                }
            }
            return height;
        }

        private static GUIContent ResolveLabel(SerializedProperty property, GUIContent fallback) {
            var definition = property.FindPropertyRelative(DefinitionBackingField);
            if(definition == null) {
                return fallback;
            }

            var id = definition.FindPropertyRelative("id")?.stringValue;
            if(!string.IsNullOrEmpty(id)) {
                return new GUIContent(id);
            }

            var name = definition.FindPropertyRelative("name")?.stringValue;
            if(!string.IsNullOrEmpty(name)) {
                return new GUIContent(name);
            }

            return fallback;
        }
    }
}
