using System;
using System.Collections.Generic;
using Fort23.Mono;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Fort23.Editor
{
    [CustomEditor(typeof(ReferenceCollector))]
    public class ReferenceCollectorEditor : UnityEditor.Editor
    {
        private string searchKey
        {
            get { return _searchKey; }
            set
            {
                if (_searchKey != value)
                {
                    _searchKey = value;
                    heroPrefab = referenceCollector.Get<Object>(searchKey);
                }
            }
        }

        private ReferenceCollector referenceCollector;

        private Object heroPrefab;

        private string _searchKey = "";

        [SerializeField] public bool isAssetBundle;

        private void DelNullReference()
        {
            var dataProperty = serializedObject.FindProperty("data");
            for (int i = dataProperty.arraySize - 1; i >= 0; i--)
            {
                var gameObjectProperty = dataProperty.GetArrayElementAtIndex(i).FindPropertyRelative("gameObject");
                if (gameObjectProperty.objectReferenceValue == null)
                {
                    dataProperty.DeleteArrayElementAtIndex(i);
                }
            }
        }

        private void OnEnable()
        {
            referenceCollector = (ReferenceCollector)target;
        }

        public override void OnInspectorGUI()
        {
            //支持撤销,Redo
            Undo.RecordObject(referenceCollector, "Changed Settings");
            var dataProperty = serializedObject.FindProperty("data");
            var isAssetBundle = serializedObject.FindProperty("isAssetBundle");
            isAssetBundle.boolValue = GUILayout.Toggle(isAssetBundle.boolValue, "是否显示打包文件夹(只有AB包设置文件用得到这个选项)");
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("添加引用"))
            {
                // Guid.NewGuid().GetHashCode().SplitToString() 是新建后默认的key
                AddReference(dataProperty, Guid.NewGuid().GetHashCode().ToString(), null);
            }

            if (GUILayout.Button("全部删除"))
            {
                dataProperty.ClearArray();
            }

            if (GUILayout.Button("删除空引用"))
            {
                DelNullReference();
            }

            if (GUILayout.Button("排序"))
            {
                referenceCollector.Sort();
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            //可以在编辑器中对searchKey进行赋值，只要输入对应的Key值，就可以点后面的删除按钮删除相对应的元素
            searchKey = EditorGUILayout.TextField(searchKey);
            //添加的可以用于选中Object的框，这里的object也是(UnityEngine.Object
            //第三个参数为是否只能引用scene中的Object
            EditorGUILayout.ObjectField(heroPrefab, typeof(Object), false);
            if (GUILayout.Button("删除"))
            {
                referenceCollector.Remove(searchKey);
                heroPrefab = null;
            }

            GUILayout.EndHorizontal();
            EditorGUILayout.Space();

            var delList = new List<int>();
            SerializedProperty property;
            //遍历ReferenceCollector中data list的所有元素，显示在编辑器中
            for (int i = referenceCollector.data.Count - 1; i >= 0; i--)
            {
                GUILayout.BeginHorizontal();
                SerializedProperty rcDataSp = dataProperty.GetArrayElementAtIndex(i);
                if (rcDataSp == null)
                {
                    continue;
                }

                SerializedProperty listSp = rcDataSp.FindPropertyRelative("isList");
                //这里的知识点在ReferenceCollector中有说
                if (dataProperty.arraySize > i)
                {
                    if (isAssetBundle.boolValue)
                    {
                        property = rcDataSp.FindPropertyRelative("isAssetBundle");
                        property.boolValue = EditorGUILayout.ToggleLeft("文件夹打AB", property.boolValue, GUILayout.Width(100));

                        listSp.boolValue = EditorGUILayout.ToggleLeft("是否是List", listSp.boolValue, GUILayout.Width(100));

                        property = rcDataSp.FindPropertyRelative("key");
                        property.stringValue = EditorGUILayout.TextField(property.stringValue, GUILayout.Width(100));
                        property = rcDataSp.FindPropertyRelative("gameObject");
                        property.objectReferenceValue = EditorGUILayout.ObjectField(property.objectReferenceValue, typeof(Object), true);
                    }
                    else
                    {
                        property = rcDataSp.FindPropertyRelative("key");
                        property.stringValue = EditorGUILayout.TextField(property.stringValue, GUILayout.Width(150));
                        property = rcDataSp.FindPropertyRelative("gameObject");
                        property.objectReferenceValue = EditorGUILayout.ObjectField(property.objectReferenceValue, typeof(Object), true);
                    }

                    if (GUILayout.Button("X"))
                    {
                        //将元素添加进删除list
                        delList.Add(i);
                    }
                }

                GUILayout.EndHorizontal();
                if (listSp.boolValue)
                {
                    string key = rcDataSp.FindPropertyRelative("key").stringValue;
                    SerializedProperty ListCollectorDatas = rcDataSp.FindPropertyRelative("ListCollectorDatas");
                    EditorGUILayout.PropertyField(ListCollectorDatas, new GUIContent(key));
                }
            }

            var eventType = Event.current.type;
            //在Inspector 窗口上创建区域，向区域拖拽资源对象，获取到拖拽到区域的对象
            if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)
            {
                // ShowForHall a copy icon on the drag
                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;

                if (eventType == EventType.DragPerform)
                {
                    DragAndDrop.AcceptDrag();
                    foreach (var o in DragAndDrop.objectReferences)
                    {
                        AddReference(dataProperty, o.name, o);
                    }
                }

                Event.current.Use();
            }

            //遍历删除list，将其删除掉
            foreach (var i in delList)
            {
                dataProperty.DeleteArrayElementAtIndex(i);
            }

            serializedObject.ApplyModifiedProperties();
            serializedObject.UpdateIfRequiredOrScript();
        }

        //添加元素
        private void AddReference(SerializedProperty dataProperty, string key, Object obj)
        {
            int index = dataProperty.arraySize;
            dataProperty.InsertArrayElementAtIndex(index);
            var element = dataProperty.GetArrayElementAtIndex(index);
            element.FindPropertyRelative("key").stringValue = key;
            element.FindPropertyRelative("gameObject").objectReferenceValue = obj;
        }
    }
}