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

namespace Jovian.PopupSystem.Editor {
    /// <summary>
    /// Custom PropertyDrawer for <see cref="PopupElementType"/>. Shows a dropdown with
    /// built-in element types plus a "Custom..." option for free-text entry.
    /// </summary>
    [CustomPropertyDrawer(typeof(PopupElementType))]
    public sealed class PopupElementTypeDrawer : PropertyDrawer {
        private static readonly string[] builtInIds = {
            "header",
            "text",
            "label_value_text",
            "image",
            "separator"
        };

        private const string customLabel = "Custom...";

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
            var idProp = FindIdProperty(property);
            if(idProp == null) {
                return EditorGUIUtility.singleLineHeight;
            }

            var currentValue = idProp.stringValue ?? "";
            var isCustom = Array.IndexOf(builtInIds, currentValue) < 0 && !string.IsNullOrEmpty(currentValue);

            return isCustom
                ? EditorGUIUtility.singleLineHeight * 2 + 2
                : EditorGUIUtility.singleLineHeight;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
            EditorGUI.BeginProperty(position, label, property);

            var idProp = FindIdProperty(property);
            if(idProp == null) {
                EditorGUI.LabelField(position, label.text, "Cannot resolve PopupElementType id field");
                EditorGUI.EndProperty();
                return;
            }

            var currentValue = idProp.stringValue ?? "";
            var builtInIndex = Array.IndexOf(builtInIds, currentValue);
            var isCustom = builtInIndex < 0 && !string.IsNullOrEmpty(currentValue);

            var options = new List<string>(builtInIds);
            options.Add(customLabel);

            int selectedIndex;
            if(builtInIndex >= 0) {
                selectedIndex = builtInIndex;
            }
            else {
                selectedIndex = options.Count - 1;
            }

            var dropdownRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
            var newIndex = EditorGUI.Popup(dropdownRect, label.text, selectedIndex, options.ToArray());

            if(newIndex != selectedIndex) {
                if(newIndex < builtInIds.Length) {
                    idProp.stringValue = builtInIds[newIndex];
                }
                else {
                    if(!isCustom) {
                        idProp.stringValue = "custom_element";
                    }
                }
            }

            var finalIsCustom = newIndex >= builtInIds.Length || (newIndex == selectedIndex && isCustom);
            if(finalIsCustom) {
                var textRect = new Rect(
                    position.x + EditorGUIUtility.labelWidth + 2,
                    position.y + EditorGUIUtility.singleLineHeight + 2,
                    position.width - EditorGUIUtility.labelWidth - 2,
                    EditorGUIUtility.singleLineHeight);
                var newValue = EditorGUI.TextField(textRect, idProp.stringValue);
                if(newValue != idProp.stringValue) {
                    idProp.stringValue = newValue;
                }
            }

            EditorGUI.EndProperty();
        }

        private static SerializedProperty FindIdProperty(SerializedProperty property) {
            var prop = property.FindPropertyRelative("id");
            if(prop != null) {
                return prop;
            }
            return property.FindPropertyRelative("<id>k__BackingField");
        }
    }
}
