#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SLZ.Marrow.Utilities;
using SLZ.Marrow.Warehouse;
using SLZ.MarrowEditor;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

namespace SLZ.Marrow
{
    [CanEditMultipleObjects]
    [CustomEditor(typeof(ImpactProperties))]
    public class ImpactPropertiesEditor : Editor
    {
        ImpactProperties script;
        private static GUIContent previewMeshGizmoIcon = null;
        private static GUIContent materialIconOn = null;
        private static GUIContent materialIconOff = null;
        public ToolbarToggle showPreviewMeshToolbarToggle;
        private static List<GameObject> allGameObjects = new List<GameObject>();
        private static List<GameObject> unattachedColsMissingImpactProperties = new List<GameObject>();
        private static List<GameObject> rbAttachedColsMissingImpactProperties = new List<GameObject>();
        VisualElement applyPhysMatsContainer;
        private static GameObject m_LastHoveredObject;
        private void OnEnable()
        {
            script = (ImpactProperties)target;
            if (previewMeshGizmoIcon == null)
            {
                previewMeshGizmoIcon = new GUIContent(EditorGUIUtility.IconContent("d_GizmosToggle On@2x"));
                previewMeshGizmoIcon.tooltip = "Toggle Preview Mesh Gizmo";
            }

            if (allGameObjects == null)
            {
                allGameObjects = new List<GameObject>();
            }

            if (allGameObjects?.Count == 0)
            {
                allGameObjects = FindObjectsOfType<GameObject>().ToList();
                foreach (GameObject gameObj in allGameObjects)
                {
                    if (gameObj.TryGetComponent<Collider>(out var gameObjHasCol) && !gameObjHasCol.isTrigger)
                    {
                        if (!gameObj.GetComponent<ImpactProperties>())
                        {
                            if (gameObjHasCol.attachedRigidbody == null)
                            {
                                if (!unattachedColsMissingImpactProperties.Contains(gameObj))
                                {
                                    unattachedColsMissingImpactProperties.Add(gameObj);
                                }
                            }
                            else
                            {
                                if (gameObjHasCol.attachedRigidbody.gameObject.GetComponent<ImpactProperties>() == null)
                                {
                                    if (!rbAttachedColsMissingImpactProperties.Contains(gameObjHasCol.attachedRigidbody.gameObject))
                                    {
                                        rbAttachedColsMissingImpactProperties.Add(gameObjHasCol.attachedRigidbody.gameObject);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        public override VisualElement CreateInspectorGUI()
        {
            string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("2956736148bce0e4eb269d7c6a26fb1f");
            VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
            VisualElement tree = visualTree.Instantiate();
            VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
            PropertyField surfaceDataCardField = tree.Q<PropertyField>("_surfaceDataCard");
            EnumField decalTypeField = tree.Q<EnumField>("DecalType");
            PropertyField surfaceDataField = tree.Q<PropertyField>("surfaceData");
            if (serializedObject.FindProperty("surfaceData") == null)
            {
                surfaceDataField.style.display = DisplayStyle.None;
            }

            applyPhysMatsContainer = tree.Q<VisualElement>("applyPhysMatsContainer");
            PhysicMaterial suggestedPhysMat = null;
            Label suggsetedPhysMatLabel = tree.Q<Label>("suggsetedPhysMatLabel");
            suggsetedPhysMatLabel.text = "";
            IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
            imguiValidationContainer.onGUIHandler = () =>
            {
            };
            if (ImpactPropertiesMeshGizmo.ShowGizmo == false)
            {
                SceneVisibilityManager.instance.EnableAllPicking();
            }

            string[] surfaceDCBarcode = new string[targets.Length];
            string[] surfaceDataName = new string[targets.Length];
            for (int t = 0; t < targets.Length; t++)
            {
                ImpactProperties impactProperties = (ImpactProperties)targets[t];
                if (impactProperties != null && impactProperties.SurfaceDataCard != null)
                {
                    surfaceDCBarcode[t] = impactProperties.SurfaceDataCard.Barcode.ToString();
                }

#if false
#endif
                ShowImpactPropsFieldHasOverride(impactProperties, decalTypeField);
                ShowImpactPropsFieldHasOverride(impactProperties, surfaceDataCardField);
            }

            suggestedPhysMat = UpdateSuggestedPhysMat(script);
            if (suggestedPhysMat != null && suggsetedPhysMatLabel.text.Replace(" (Instance)", "").Trim() != suggestedPhysMat.name.Trim())
            {
                suggsetedPhysMatLabel.text = suggestedPhysMat.name;
            }

            surfaceDataCardField.RegisterValueChangeCallback((evt) =>
            {
                for (int t = 0; t < targets.Length; t++)
                {
                    ImpactProperties impactProperties = (ImpactProperties)targets[t];
                    if (impactProperties != null && impactProperties.SurfaceDataCard != null && impactProperties.SurfaceDataCard.IsValid() && impactProperties.SurfaceDataCard.TryGetDataCard(out SurfaceDataCard sdc))
                    {
                        if (sdc != null && sdc.Barcode.ToString() != surfaceDCBarcode[t])
                        {
                            ImpactPropertiesMeshGizmo.DisableGizmo(impactProperties);
                            Undo.RecordObject(impactProperties, impactProperties.name + "SD Card updated");
                            surfaceDCBarcode[t] = sdc.Barcode.ToString();
                            EditorUtility.SetDirty(impactProperties);
                            if (PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Variant)
                            {
                                PrefabUtility.RecordPrefabInstancePropertyModifications(impactProperties);
                                ShowImpactPropsFieldHasOverride(impactProperties, surfaceDataCardField);
                            }
                        }

                        suggestedPhysMat = UpdateSuggestedPhysMat(impactProperties);
                        if (suggestedPhysMat != null && suggsetedPhysMatLabel.text.Replace(" (Instance)", "").Trim() != suggestedPhysMat.name.Trim())
                        {
                            suggsetedPhysMatLabel.text = suggestedPhysMat.name;
                        }
                    }
                    else
                    {
                        if (impactProperties != null && ImpactPropertiesMeshGizmo.ShowGizmo)
                        {
                            ImpactPropertiesMeshGizmo.DisableGizmo(impactProperties);
                        }
                    }
                }
            });
            decalTypeField.RegisterValueChangedCallback((evt) =>
            {
                foreach (UnityEngine.Object target in targets)
                {
                    ImpactProperties impactProperties = (ImpactProperties)target;
                    Undo.RecordObject(impactProperties, impactProperties.name + "DecalType updated");
                    impactProperties.decalType = (ImpactProperties.DecalType)decalTypeField.value;
                    EditorUtility.SetDirty(impactProperties);
                    if (PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Variant)
                    {
                        PrefabUtility.RecordPrefabInstancePropertyModifications(impactProperties);
                        ShowImpactPropsFieldHasOverride(impactProperties, decalTypeField);
                    }
                }
            });
            decalTypeField.value = script.decalType;
#if false
#endif
            Texture physmatIcon = EditorGUIUtility.ObjectContent(null, typeof(PhysicMaterial)).image;
            Image physmatIconImage = new Image();
            physmatIconImage.image = physmatIcon;
            physmatIconImage.style.flexShrink = 0;
            physmatIconImage.StretchToParentSize();
            VisualElement suggestPhysMatsIcon = tree.Q<VisualElement>("suggestPhysMatsIcon");
            suggestPhysMatsIcon.style.flexShrink = 0;
            suggestPhysMatsIcon.Add(physmatIconImage);
            Button applyPhysMatsButton = tree.Q<Button>("applyPhysMatsButton");
            applyPhysMatsButton.style.flexShrink = 0;
            applyPhysMatsButton.tooltip = "Applies the suggested Physics Material to this Impact Properties sibling collider(s)";
            applyPhysMatsButton.clickable.clicked += () =>
            {
                for (int t = 0; t < targets.Length; t++)
                {
                    ImpactProperties impactProperties = (ImpactProperties)targets[t];
                    if (impactProperties != null && impactProperties.SurfaceDataCard != null && impactProperties.SurfaceDataCard.IsValid() && suggestedPhysMat != null)
                    {
                        if (impactProperties.TryGetComponent<Collider>(out var siblingCol))
                        {
                            if (siblingCol.sharedMaterial != suggestedPhysMat)
                            {
                                if (PrefabUtility.HasPrefabInstanceAnyOverrides(impactProperties.gameObject, false))
                                {
                                    siblingCol.sharedMaterial = suggestedPhysMat;
                                }
                                else
                                {
                                    siblingCol.sharedMaterial = suggestedPhysMat;
                                }

                                EditorUtility.SetDirty(siblingCol);
                                if (PrefabUtility.GetPrefabAssetType(siblingCol) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(siblingCol) == PrefabAssetType.Variant)
                                {
                                    PrefabUtility.RecordPrefabInstancePropertyModifications(siblingCol);
                                }
                            }
                        }
                    }
                }
            };
            Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
            marrowDocsButton.clickable.clicked += () =>
            {
                Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ImpactProperties");
            };
            IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
            imguiInspector.onGUIHandler = () =>
            {
                DrawDefaultInspector();
            };
            showPreviewMeshToolbarToggle = tree.Q<ToolbarToggle>("showPreviewMeshToolbarToggle");
            Image showPreviewMeshIconImage = new Image
            {
                image = previewMeshGizmoIcon.image
            };
            showPreviewMeshToolbarToggle.Add(showPreviewMeshIconImage);
            showPreviewMeshToolbarToggle.RegisterValueChangedCallback(evt =>
            {
                ImpactPropertiesMeshGizmo.ShowGizmo = showPreviewMeshToolbarToggle.value;
                UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
                if (ImpactPropertiesMeshGizmo.ShowGizmo)
                {
                    SurfaceDataPainterOverlay.DoWithInstances(instance => instance.displayed = true);
                    SurfaceDataPainterOverlay.DoWithInstances(instance => instance.collapsed = false);
                }
                else
                {
                    SurfaceDataPainterOverlay.DoWithInstances(instance => instance.displayed = false);
                }
            });
            SliderInt gizmoVisRangeSlider = tree.Q<SliderInt>("gizmoVisRangeSlider");
            gizmoVisRangeSlider.RegisterValueChangedCallback(evt =>
            {
                ImpactPropertiesMeshGizmo.gizmoVisRange = gizmoVisRangeSlider.value;
            });
            showPreviewMeshToolbarToggle.SetValueWithoutNotify(ImpactPropertiesMeshGizmo.ShowGizmo);
            gizmoVisRangeSlider.SetValueWithoutNotify((int)ImpactPropertiesMeshGizmo.gizmoVisRange);
            return tree;
        }

        private PhysicMaterial UpdateSuggestedPhysMat(ImpactProperties impactProperties)
        {
            bool colMatSuggestedMismatch = false;
            PhysicMaterial suggestedPhysMat;
            impactProperties.TryGetComponent(out Rigidbody ipRigidBody);
            if (impactProperties.SurfaceDataCard.TryGetDataCard(out SurfaceDataCard sdc))
            {
                if (ipRigidBody)
                {
                    suggestedPhysMat = (PhysicMaterial)AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(sdc.PhysicsMaterial.AssetGUID));
                }
                else
                {
                    suggestedPhysMat = (PhysicMaterial)AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(sdc.PhysicsMaterialStatic.AssetGUID));
                    ;
                }

                for (int t = 0; t < targets.Length; t++)
                {
                    ImpactProperties impactProp = (ImpactProperties)targets[t];
                    if (impactProp.TryGetComponent<Collider>(out var siblingColSelected))
                    {
                        if (siblingColSelected.sharedMaterial != suggestedPhysMat)
                        {
                            colMatSuggestedMismatch = true;
                        }
                    }
                }

                if (impactProperties.TryGetComponent<Collider>(out var siblingCol))
                {
                    if (siblingCol.sharedMaterial != suggestedPhysMat)
                    {
                        applyPhysMatsContainer.style.display = DisplayStyle.Flex;
                    }
                    else if (colMatSuggestedMismatch)
                    {
                        applyPhysMatsContainer.style.display = DisplayStyle.Flex;
                    }
                    else
                    {
                        applyPhysMatsContainer.style.display = DisplayStyle.None;
                    }
                }

                return suggestedPhysMat;
            }

            return null;
        }

        private void ShowImpactPropsFieldHasOverride(ImpactProperties impactProperties, VisualElement overrideField)
        {
            Color overrideMarginColor = new Color32(5, 147, 224, 255);
            if (PrefabUtility.HasPrefabInstanceAnyOverrides(impactProperties.gameObject, false))
            {
                PropertyModification[] prefabOverrides = PrefabUtility.GetPropertyModifications(impactProperties.gameObject);
                int decalOverrideCount = 0;
                int sdCardOverrideCount = 0;
                int obsSDOverrideCount = 0;
                foreach (var prefabOverride in prefabOverrides)
                {
                    if (PrefabStageUtility.GetCurrentPrefabStage() == null)
                    {
                        if (prefabOverride.propertyPath == "_surfaceDataCard._barcode._id" && overrideField.name == "_surfaceDataCard")
                        {
                            overrideField.style.marginLeft = 3;
                            overrideField.style.paddingLeft = 3;
                            overrideField.style.unityFontStyleAndWeight = FontStyle.Bold;
                            overrideField.style.borderLeftColor = overrideMarginColor;
                            overrideField.style.borderLeftWidth = 3;
                            sdCardOverrideCount++;
                        }

                        if (prefabOverride.propertyPath == "decalType" && overrideField.name == "DecalType")
                        {
                            overrideField.style.marginLeft = 3;
                            overrideField.style.paddingLeft = 3;
                            overrideField.style.unityFontStyleAndWeight = FontStyle.Bold;
                            overrideField.style.borderLeftColor = overrideMarginColor;
                            overrideField.style.borderLeftWidth = 3;
                            decalOverrideCount++;
                        }

                        if (prefabOverride.propertyPath == "surfaceData" && overrideField.name == "surfaceData")
                        {
                            overrideField.style.paddingLeft = 3;
                            overrideField.style.unityFontStyleAndWeight = FontStyle.Bold;
                            overrideField.style.borderLeftColor = overrideMarginColor;
                            overrideField.style.borderLeftWidth = 3;
                            obsSDOverrideCount++;
                        }
                    }
                }

                if (sdCardOverrideCount == 0 && overrideField.name == "_surfaceDataCard")
                {
                    overrideField.style.marginLeft = 0;
                    overrideField.style.paddingLeft = 0;
                    overrideField.style.unityFontStyleAndWeight = FontStyle.Normal;
                    overrideField.style.borderLeftColor = overrideMarginColor;
                    overrideField.style.borderLeftWidth = 0;
                }

                if (decalOverrideCount == 0 && overrideField.name == "DecalType")
                {
                    overrideField.style.paddingLeft = 0;
                    overrideField.style.unityFontStyleAndWeight = FontStyle.Normal;
                    overrideField.style.borderLeftColor = overrideMarginColor;
                    overrideField.style.borderLeftWidth = 0;
                }

                if (sdCardOverrideCount == 0 && overrideField.name == "surfaceData")
                {
                    overrideField.style.paddingLeft = 0;
                    overrideField.style.unityFontStyleAndWeight = FontStyle.Normal;
                    overrideField.style.borderLeftColor = overrideMarginColor;
                    overrideField.style.borderLeftWidth = 0;
                }
            }
        }

        private void ApplyObsoleteSurfaceDataMats(ImpactProperties impactProperties)
        {
            object[] parametersArray = new Transform[]
            {
                impactProperties.transform
            };
            Type type = impactProperties.GetType();
            MethodInfo methodInfo = type.GetMethod("ObsoleteUpdateMaterialRecursive", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            methodInfo.Invoke(impactProperties, parametersArray);
        }

        private void ApplySurfaceDataCardMats(ImpactProperties impactProperties)
        {
            object[] parametersArray = new Transform[]
            {
                impactProperties.transform
            };
            Type type = impactProperties.GetType();
            MethodInfo methodInfo = type.GetMethod("ApplyPhysMatsRecursive", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            methodInfo.Invoke(impactProperties, parametersArray);
        }

        private static void OnGlobalSceneGUI(SceneView sceneView)
        {
            if (ImpactPropertiesMeshGizmo.ShowGizmo)
            {
                PickHoverObject();
                GenerateHoverText();
            }

            if (ImpactProperties.showMissingImpactProperties)
            {
                foreach (GameObject gameObj in unattachedColsMissingImpactProperties)
                {
                    Gizmos.color = Color.red;
                    DrawGizmoHelper.DrawText("MISSING IMPACT PROPS", gameObj.transform.position);
                }

                foreach (GameObject gameObj in rbAttachedColsMissingImpactProperties)
                {
                    Gizmos.color = Color.red;
                    DrawGizmoHelper.DrawText("ATTACHED RB MISSING IMPACT PROPS", gameObj.transform.position);
                }
            }
        }

        public static void PickHoverObject()
        {
            var evt = Event.current;
            if (evt.type == EventType.MouseMove)
            {
                var picked = HandleUtility.PickGameObject(evt.mousePosition, false);
                if (picked != m_LastHoveredObject)
                {
                    m_LastHoveredObject = picked;
                }
            }
            else if (evt.type == EventType.MouseDrag && evt.button == 1)
            {
                var picked = HandleUtility.PickGameObject(evt.mousePosition, false);
                if (picked != m_LastHoveredObject)
                {
                    m_LastHoveredObject = picked;
                }
            }

            HoverHighlight();
        }

        [InitializeOnLoadMethod]
        static void InitSceneGUICallback()
        {
            SceneView.duringSceneGui += OnGlobalSceneGUI;
        }

        private static GameObject lastHoveredObject;
        private static Collider lastHighlightedCollider = null;
        private static List<Collider> currentSelectedColliders = new List<Collider>();
        private static List<Collider> lastSelectedColliders = new List<Collider>();
        private static Color selectColor = new Color(0.5f, 0.5f, 0.5f);
        private static Color hoverColor = new Color(0.25f, 0.25f, 0.25f);
        private static HashSet<int> selectedColliderIDs = new HashSet<int>();
        static void HoverHighlight()
        {
            if (ImpactPropertiesMeshGizmo.ShowGizmo)
            {
                var evt = Event.current;
                var selectedGOs = Selection.gameObjects;
                selectedColliderIDs.Clear();
                currentSelectedColliders.Clear();
                foreach (var selected in selectedGOs)
                {
                    if (selected.TryGetComponent<Collider>(out var selectedCollider) && !selectedCollider.isTrigger)
                    {
                        currentSelectedColliders.Add(selectedCollider);
                        selectedColliderIDs.Add(selectedCollider.GetInstanceID());
                    }
                }

                var deselected = lastSelectedColliders.Except(currentSelectedColliders);
                foreach (var lastSelected in deselected)
                {
                    ImpactPropertiesMeshGizmo.HighlightGizmo(lastSelected, false);
                }

                var newSelection = currentSelectedColliders.Except(lastSelectedColliders);
                foreach (var newSelected in newSelection)
                {
                    ImpactPropertiesMeshGizmo.HighlightGizmo(newSelected, selectColor);
                }

                lastSelectedColliders.Clear();
                foreach (var selectedCollider in currentSelectedColliders)
                {
                    lastSelectedColliders.Add(selectedCollider);
                }

                if (evt.type != EventType.Repaint)
                {
                    switch (evt.type)
                    {
                        case EventType.MouseMove:
                        case EventType.MouseDown:
                        case EventType.MouseUp:
                            var picked = HandleUtility.PickGameObject(evt.mousePosition, out _);
                            if (picked != null && (lastHoveredObject == null || picked != lastHoveredObject))
                            {
                                Collider pickedCollider = null;
                                if (picked.activeInHierarchy)
                                {
                                    if (!picked.TryGetComponent<Collider>(out pickedCollider) || pickedCollider.isTrigger)
                                    {
                                        if (picked.TryGetComponent<ImpactPropertiesMeshGizmo>(out var gizmo) && !gizmo.Collider.isTrigger)
                                        {
                                            pickedCollider = gizmo.Collider;
                                        }
                                    }

                                    if (pickedCollider && selectedColliderIDs.Contains(pickedCollider.GetInstanceID()))
                                    {
                                        if (lastHighlightedCollider && !selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
                                        {
                                            ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
                                        }

                                        lastHighlightedCollider = null;
                                        lastHoveredObject = null;
                                        return;
                                    }
                                }

                                if (pickedCollider)
                                {
                                    if (lastHighlightedCollider)
                                    {
                                        if (!selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
                                        {
                                            ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
                                        }

                                        lastHighlightedCollider = null;
                                    }

                                    if (!lastHighlightedCollider || pickedCollider != lastHighlightedCollider)
                                    {
                                        ImpactPropertiesMeshGizmo.HighlightGizmo(pickedCollider, hoverColor);
                                        lastHighlightedCollider = pickedCollider;
                                    }
                                }
                                else
                                {
                                    if (lastHighlightedCollider)
                                        ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
                                }

                                lastHoveredObject = picked;
                            }
                            else if (picked == null)
                            {
                                if (lastHoveredObject)
                                {
                                    if (lastHighlightedCollider)
                                    {
                                        if (!selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
                                        {
                                            ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
                                        }

                                        lastHighlightedCollider = null;
                                    }

                                    lastHoveredObject = null;
                                }

                                if (lastHighlightedCollider)
                                {
                                    if (!selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
                                    {
                                        ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
                                    }

                                    lastHighlightedCollider = null;
                                }
                            }

                            break;
                    }
                }
            }
        }

        public static void GenerateHoverText()
        {
            if (m_LastHoveredObject == null)
            {
                return;
            }

            Camera sceneCam = SceneView.lastActiveSceneView.camera;
            Vector3 mousePosition = Event.current.mousePosition;
            mousePosition.y = SceneView.lastActiveSceneView.camera.pixelHeight - mousePosition.y;
            mousePosition.z = sceneCam.nearClipPlane + 0.5f;
            Vector3 cursorPos = sceneCam.ScreenToWorldPoint(mousePosition);
            int fontSize = 15;
            Collider hitCol = m_LastHoveredObject?.GetComponentInParent<Collider>();
            string mouseInfoString = "";
            GUIStyle linkHandleStyle = new GUIStyle();
            linkHandleStyle.richText = true;
            ;
            if (hitCol != null && hitCol.isTrigger == false)
            {
                if (Camera.current != null && Camera.current == SceneView.lastActiveSceneView.camera && Vector3.Dot(hitCol.transform.position - Camera.current.transform.position, Camera.current.transform.forward) < ImpactPropertiesMeshGizmo.gizmoVisRange)
                {
                    if (hitCol.attachedRigidbody == null)
                    {
                        ImpactProperties impactProp = hitCol.GetComponent<ImpactProperties>();
                        ImpactProperties.surfaceDataBrushTarget = null;
                        if (impactProp == null)
                        {
                            mouseInfoString = $"\n<size={fontSize}><color=red>     <b>MISSING IMPACT PROPERTIES</b></color>\n";
                            if (ImpactProperties.surfaceDataBrush)
                            {
                                string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
                                mouseInfoString += $"     <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
                            }
                            else
                            {
                                mouseInfoString += $"     <color=grey>Brush: No brush selected</color></size>";
                            }
                        }
                        else
                        {
                            mouseInfoString = "";
                            if (impactProp.SurfaceDataCard != null && impactProp.SurfaceDataCard.IsValid() && impactProp.SurfaceDataCard.TryGetDataCard(out var dataCard))
                            {
                                mouseInfoString = $"\n<size={fontSize}><color=white>     Surface Data: {dataCard.Title}</color>\n";
                                ImpactProperties.surfaceDataBrushTarget = dataCard;
                            }
                            else
                            {
                                mouseInfoString = $"\n<size={fontSize}><color=red>     Surface Data: <b>SURFACE DATA MISSING</b></color>\n";
                            }

                            if (ImpactProperties.surfaceDataBrush)
                            {
                                string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
                                mouseInfoString += $"     <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
                            }
                            else
                            {
                                mouseInfoString += $"     <color=grey>Brush: No brush selected</color></size>";
                            }
                        }
                    }
                    else
                    {
                        ImpactProperties impactPropsRB = hitCol.attachedRigidbody.GetComponent<ImpactProperties>();
                        ImpactProperties.surfaceDataBrushTarget = null;
                        if (impactPropsRB == null)
                        {
                            mouseInfoString = $"\n<size={fontSize}><color=red>     <b>ATTACHED RB MISSING IMPACT PROPERTIES</b></color>\n";
                            if (ImpactProperties.surfaceDataBrush)
                            {
                                string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
                                mouseInfoString += $"     <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
                            }
                            else
                            {
                                mouseInfoString += $"     <color=grey>Brush: No brush selected</color></size>";
                            }
                        }
                        else
                        {
                            mouseInfoString = "";
                            if (impactPropsRB.SurfaceDataCard != null && impactPropsRB.SurfaceDataCard.IsValid() && impactPropsRB.SurfaceDataCard.TryGetDataCard(out var rbDataCard))
                            {
                                mouseInfoString = $"\n<size={fontSize}><color=white>     Surface Data: {rbDataCard.Title}</color>\n";
                                ImpactProperties.surfaceDataBrushTarget = rbDataCard;
                            }
                            else
                            {
                                mouseInfoString = $"\n<size={fontSize}><color=red>     Surface Data: <b>SURFACE DATA MISSING</b></color>\n";
                            }

                            if (ImpactProperties.surfaceDataBrush)
                            {
                                string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
                                mouseInfoString += $"     <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
                            }
                            else
                            {
                                mouseInfoString += $"     <color=grey>Brush: No brush selected</color></size>";
                            }
                        }
                    }

                    Handles.Label(cursorPos, $"{mouseInfoString}", linkHandleStyle);
                }
            }
        }
    }
}
#endif