using System;
using System.Collections.Generic;
using System.Linq;
using Jovian.Utilities;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Jovian.InspectorTools
{
    /// <summary>
    /// Finds all objects in the project matching <c>filter</c> string and lists alphabetically in a dropdown (if they are <c>assetType</c>)
    /// </summary>
    public class AssetDropdownAttribute : PropertyAttribute
    {
        public readonly Type assetType;
        public readonly string filter;

        public AssetDropdownAttribute(Type assetType, string filter)
        {
            this.assetType = assetType;
            this.filter = filter;
        }
    }
}

#if UNITY_EDITOR
namespace Jovian.InspectorTools.Internal
{
    using UnityEditor;

    [CustomPropertyDrawer(typeof(AssetDropdownAttribute))]
    public class AssetDropdownAttributeDrawer : PropertyDrawer
    {
        private bool isInitialized;
        private bool hasValidTarget;
        private List<Object> objects;
        private string[] values;

        private int selectedIndex = -1;

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (property.propertyType != SerializedPropertyType.ObjectReference)
            {
                Debug.LogError("Required property to be an ObjectReference.");
                EditorGUI.PropertyField(position, property, label);
                return;
            }

            if (!isInitialized)
            {
                Initialize();
            }

            EditorGUI.BeginChangeCheck();
            selectedIndex = property.objectReferenceValue != null ? Array.IndexOf(values, property.objectReferenceValue.name) : -1;
            selectedIndex = EditorGUI.Popup(position, label.text, selectedIndex, values);

            if (Event.current.type == EventType.MouseDown && Event.current.modifiers == EventModifiers.Shift &&
                GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
            {
                isInitialized = false;
            }

            if (EditorGUI.EndChangeCheck())
            {
                property.objectReferenceValue = objects[selectedIndex];
                property.serializedObject.ApplyModifiedProperties();
            }
        }

        private void Initialize()
        {
            AssetDropdownAttribute assetDropdownAttribute = (AssetDropdownAttribute)attribute;

            objects = AssetUtility.FindAllObjectsInProject(assetDropdownAttribute.assetType, assetDropdownAttribute.filter);
            objects.Sort(SortByName);
            values = objects.Select(obj => obj.name).ToArray();

            isInitialized = true;
        }

        private static int SortByName(Object a, Object b) {
            return string.Compare(a.name, b.name, StringComparison.Ordinal);
        }
    }
}
#endif
