private void AddEntries(ArrayElementBuilder elementBuilder, int count) =>
 elementBuilder.schedule.Execute(() => elementBuilder.value += count);
        public override VisualElement CreateInspectorGUI()
        {
            if (Selection.activeObject is null || Selection.objects.Length == 0)
            {
                return(base.CreateInspectorGUI());
            }
            if (!GetType().IsSubclassOf(typeof(ScriptableObject)) || categoryList is null || categoryList.Count == 0)
            {
                return(base.CreateInspectorGUI());
            }
            if (!idConfig.AAIConfiguration().enableCustomEditors)
            {
                return(base.CreateInspectorGUI());
            }

            var baseStyleSheet = idConfig.GetStyleSheet("AAIDefaultEditorBase");

            if (defaultStyleSheet is null)
            {
                defaultStyleSheet = idConfig.GetStyleSheet("AAIDefaultEditorStyle");
            }
            if (defaultStyleSheet is null)
            {
                Debug.Log("Could not locate AAIDefaultEditorStyle");
            }

            serializedObject.Update();

            defaultRoot = new VisualElement();

            defaultRoot.styleSheets.Add(baseStyleSheet);
            defaultRoot.styleSheets.Add(defaultStyleSheet);
            defaultRoot.AddToClassList("rootContainer");

            var boxContainer = new Box();

            boxContainer.AddToClassList("mainBoxContainer");

            if (beforeDefaultElements == null)
            {
                beforeDefaultElements = new VisualElement();
            }
            beforeDefaultElements.name = "beforeDefaultElements";
            beforeDefaultElements.AddToClassList("beforeDefaultElements");
            defaultRoot.Add(beforeDefaultElements);

            categoryList.ForEach(x =>
            {
                if (x is null)
                {
                    return;
                }
                x.AddToClassList("categoryFoldout");
                boxContainer.Add(x);
            });

            m_ScrollView = new ScrollView();
            boxContainer.Add(m_ScrollView);

            keyData = classDataDictionary.Keys.ToList();

            #region Property Iteration

            var property = serializedObject.GetIterator();
            if (property.NextVisible(true))
            {
                do
                {
                    // -- Shortening name for ease of typing -------------
                    var propPath = property.propertyPath;

                    // -- Skip over excluded fields ----------------------
                    if (excludedFields.Contains(propPath) && serializedObject.targetObject != null)
                    {
                        continue;
                    }

                    // -- Property row VisualElement ---------------------
                    var propertyRow    = new VisualElement();
                    var propertyColumn = new VisualElement();
                    propertyRow.AddToClassList("propertyRow");
                    propertyColumn.AddToClassList("propertyColumn");

                    // -- Property fallback field ------------------------
                    var propertyField = new PropertyField(property)
                    {
                        name = "PropertyField:" + propPath
                    };

                    // -- Determine if current property is field data ----
                    if (!classDataDictionary[Enumerable.First(keyData)].fieldDatas.Keys.Contains(propPath))
                    {
                        switch (propPath)
                        {
                        case "m_Script" when serializedObject.targetObject != null:
                            propertyField.visible = false;     // @formatter:off
                            propertyField.SetEnabled(false);
                            break;

                        default:
                            if (property.IsReallyArray() && serializedObject.targetObject != null)
                            {
                                var copiedProperty    = property.Copy();
                                var imDefaultProperty = new IMGUIContainer(() =>
                                {
                                    DoDrawDefaultIMGUIProperty(serializedObject, copiedProperty);
                                })
                                {
                                    name = propPath
                                };
                                m_ScrollView.Add(imDefaultProperty);
                            }
                            break;     // @formatter:on
                        }
                    }
                    else
                    {
                        var propertyData = classDataDictionary[Enumerable.First(keyData)].fieldDatas[propPath];
                        switch (propertyData.fieldInfo)
                        {
                        // -- String/TextField Elements --------------
                        case FieldInfo a when a.FieldType == typeof(string):
                        case FieldInfo b when b.FieldType == typeof(PropertyName):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"String: {propPath}");
                            }

                            var propertyTextLabel = new Label(property.displayName);
                            propertyTextLabel.name = $"{propPath}Label";
                            var propertyTextField = new TextField
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}Text"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyTextLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyTextField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyTextLabel.AddToClassList("propertyTextLabel");
                            propertyTextField.AddToClassList("propertyTextField");
                            propertyRow.Add(propertyTextLabel);
                            propertyRow.Add(propertyTextField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Integer Elements -----------------------
                        case FieldInfo a when a.FieldType == typeof(int):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Integer: {propPath}");
                            }
                            var propertyIntegerLabel = new Label(property.displayName);
                            propertyIntegerLabel.name = $"{propPath}Label";
                            var propertyIntegerField = new IntegerField
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}Integer"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyIntegerLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyIntegerField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyIntegerLabel.AddToClassList("propertyIntegerLabel");
                            propertyIntegerField.AddToClassList("propertyIntegerField");
                            propertyRow.Add(propertyIntegerLabel);
                            propertyRow.Add(propertyIntegerField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Float Elements -------------------------
                        case FieldInfo a when a.FieldType == typeof(float):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Float: {propPath}");
                            }

                            var propertyFloatLabel = new Label(property.displayName);
                            propertyFloatLabel.name = $"{propPath}Label";
                            var propertyFloatField = new FloatField
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}Float"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyFloatLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyFloatField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyFloatLabel.AddToClassList("propertyFloatLabel");
                            propertyFloatField.AddToClassList("propertyFloatField");
                            propertyRow.Add(propertyFloatLabel);
                            propertyRow.Add(propertyFloatField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Bool/Toggle Elements -------------------
                        case FieldInfo a when a.FieldType == typeof(bool):
                        case FieldInfo b when b.FieldType == typeof(Toggle):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Toggle: {propPath}");
                            }

                            var propertyToggleLabel = new Label(property.displayName);
                            propertyToggleLabel.name = $"{propPath}ToggleLabel";
                            var propertyToggleSpacer = new VisualElement();
                            var propertyToggleField  = new Toggle
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}ToggleField"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyToggleLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyToggleField.tooltip = propertyData.categoryAttr.toolTip;
                            }


                            propertyToggleLabel.AddToClassList("propertyToggleLabel");
                            propertyToggleLabel.AddToClassList("propertyToggleSpacer");
                            propertyToggleField.AddToClassList("propertyToggleField");
                            propertyRow.Add(propertyToggleLabel);
                            propertyRow.Add(propertyToggleField);
                            propertyRow.Add(propertyToggleSpacer);
                            propertyRow.RemoveFromClassList("propertyRow");
                            propertyRow.AddToClassList("propertyToggleRow");
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Dictionary Elements --------------------
                        case FieldInfo a when typeof(IDictionary).IsAssignableFrom(a.FieldType):
                        case FieldInfo b when typeof(IDictionary).IsSubclassOf(b.FieldType):
                            var dictionaryFoldout = new Foldout {
                                text = property.displayName
                            };
                            dictionaryFoldout.AddToClassList("arrayFoldout");
                            dictionaryFoldout.value = false;

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                dictionaryFoldout.tooltip = propertyData.categoryAttr.toolTip;
                                propertyColumn.tooltip    = propertyData.categoryAttr.toolTip;
                            }

                            dictionaryFoldout.Add(propertyField);
                            propertyColumn.Add(dictionaryFoldout);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyColumn);
                            break;

                        // -- List/Set Elements ----------------------
                        case FieldInfo a when typeof(IList).IsAssignableFrom(a.FieldType):
                        case FieldInfo b when typeof(IList).IsSubclassOf(b.FieldType):
                        case FieldInfo c when typeof(ISet <>).IsAssignableFrom(c.FieldType):
                        case FieldInfo d when typeof(ISet <>).IsSubclassOf(d.FieldType):
                            var arrayElementBuilder = new ArrayElementBuilder(property, propertyData);

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyRow.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyRow.Add(arrayElementBuilder);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Object Elements ----------------------
                        case FieldInfo a when a.FieldType == typeof(Object):
                        case FieldInfo b when typeof(Object).IsSubclassOf(b.FieldType):
                        case FieldInfo c when typeof(Object).IsAssignableFrom(c.FieldType):
                            var propertyObjectLabel = new Label(property.displayName);
                            propertyObjectLabel.name = $"{propPath}ObjectLabel";
                            var propertyObjectField = new ObjectField
                            {
                                objectType  = propertyData.fieldType,
                                bindingPath = propPath,
                                name        = $"{propPath}ObjectField"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyObjectLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyObjectField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyObjectLabel.AddToClassList("propertyObjectLabel");
                            propertyObjectField.AddToClassList("propertyObjectField");
                            propertyRow.Add(propertyObjectLabel);
                            propertyRow.Add(propertyObjectField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Fallback Test: Name: {propPath} Type: {property.type} Array: {property.isArray} : {property.propertyType}");
                            }
                            break;

                        default:
                            if (property.IsReallyArray())
                            {
                                propertyColumn.Add(propertyField);
                                boxContainer.Q(propertyData.categoryAttr.category).Add(propertyColumn);
                            }

                            // else propertyColumn.Add(propertyField);
                            //
                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyColumn.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            //
                            // boxContainer.Q(propertyData.categoryAttr.category).Add(propertyColumn);
                            break;
                        }
                    }
                } while (property.NextVisible(false));
            }

            #endregion

            foreach (var foldoutList in m_ScrollView.Query <Foldout>().ToList())
            {
                foldoutList.RegisterValueChangedCallback(e =>
                {
                    // TODO Remove this:
                    if (!(e.target is Foldout fd))
                    {
                        return;
                    }
                    Debug.Log($" {fd.name}");
                    var path      = fd.bindingPath;
                    var container = m_ScrollView.Q <IMGUIContainer>(path);
                    RecomputeSize(container);
                });
            }

            foreach (var foldoutList in m_ScrollView.Query <AnimatedFoldout>().ToList())
            {
                foldoutList.RegisterValueChangedCallback(e =>
                {
                    // TODO Remove this:
                    if (!(e.target is Foldout fd))
                    {
                        return;
                    }
                    Debug.Log($" {fd.name}");
                    var path      = fd.bindingPath;
                    var container = m_ScrollView.Q <IMGUIContainer>(path);
                    RecomputeSize(container);
                });
            }

            VisualElement defaultCategory = null;
            for (var i = 0; i < categoryList.Count; i++)
            {
                VisualElement x;
                if (isAnimated)
                {
                    x = categoryList[i].Q <AnimatedFoldout>();
                }
                else
                {
                    x = categoryList[i].Q <Foldout>();
                }
                if (x.name != "Default")
                {
                    continue;
                }
                defaultCategory = x;
                break;
            }

            if (defaultCategory.childCount == 0)
            {
                defaultCategory.style.display = DisplayStyle.None;
            }

            if (isAnimated)
            {
                var listItems = boxContainer.Query <AnimatedFoldout>().ToList();
                listItems.ForEach(x => foldout.Add((AnimatedFoldout)x));
            }
            else
            {
                var listItems = boxContainer.Query <Foldout>().ToList();
                listItems.ForEach(x => foldout.Add((Foldout)x));
            }

            foldout.ForEach(x =>
            {
                Toggle toggleItem;
                if (isAnimated)
                {
                    var item        = (AnimatedFoldout)x;
                    var contentItem = item.Q(null, AnimatedFoldout.expanderUssClassName);
                    contentItem.ToggleInClassList("categoryFoldoutClosed");
                    item.Q(null, "unity-toggle__checkmark").AddToClassList("toggleCheckmark");
                    item.RegisterCallback((ChangeEvent <bool> evt) =>
                    {
                        var targetElement = evt.target as VisualElement;

                        if (targetElement == item)
                        {
                            item.value = evt.newValue;
                        }

                        if (targetElement.parent == item || targetElement == item || targetElement.contentContainer == item)
                        {
                            item.value = evt.newValue;
                            // if (evt.newValue) item.contentContainer.style.display = DisplayStyle.Flex;

                            // if (!evt.newValue) // @formatter:off
                            // {
                            //     item.schedule.Execute(() =>
                            //     {
                            //         item.contentContainer.style.display = DisplayStyle.None;
                            //     }).StartingIn(500);
                            //     item.schedule.Execute(() =>
                            //     {
                            //         contentItem.style.display = DisplayStyle.None;
                            //     }).StartingIn(600); // @formatter:on
                            // }
                        }
                        else
                        {
                            item.expander.TriggerExpanderResize(true);
                        }
                    }); // @formatter:on
                }
                else
                {
                    var item   = (Foldout)x;
                    toggleItem = item.Q <Toggle>();
                    toggleItem.ToggleInClassList("categoryFoldoutClosed");
                    item.Q(null, "unity-toggle__checkmark").AddToClassList("toggleCheckmark");
                }
            });

            serializedObject.ApplyModifiedProperties();

            if (afterDefaultElements == null)
            {
                afterDefaultElements = new VisualElement();
            }
            afterDefaultElements.name = "afterDefaultElements";
            afterDefaultElements.AddToClassList("afterDefaultElements");

            boxContainer.Add(afterDefaultElements);
            defaultRoot.Add(boxContainer);

            defaultRoot.RegisterCallback <GeometryChangedEvent>(ExecutePostBuildTask);
            defaultRoot.schedule.Execute(ExecuteLocalDeferredTask).StartingIn(0);

            return(defaultRoot);
        }