using UnityEditor;
using UnityEngine;
using System.Linq;
using NUnit.Framework.Internal.Commands;

[InitializeOnLoad]
public static class EditorCustom
{
    static EditorCustom()
    {
        SceneView.duringSceneGui += OnSceneGUI;
    }

    private static void OnSceneGUI(SceneView sceneView)
    {
        Event e = Event.current;

        if (e.type == EventType.MouseDown && e.button == 1)
        {
            // Nodes prüfen
            GameManager gm = GameObject.FindFirstObjectByType<GameManager>();
            if (!gm) return;

            Node[] selectedNodes = Selection.gameObjects
                .Select(g => g.GetComponent<Node>())
                .Where(n => n != null)
                .ToArray();

            GenericMenu menu = new GenericMenu();

            if (selectedNodes.Length == 2)
            {
                menu.AddItem(new GUIContent("Connect Selected Nodes"), false, () =>
                {
                    Connection con = gm.GetConnections().Find(con =>
                        (con.nodeA == selectedNodes[0] && con.nodeB == selectedNodes[1]) ||
                        (con.nodeA == selectedNodes[1] && con.nodeB == selectedNodes[0]));
                    if (con != null)
                        con.allowed = true;
                    else
                        gm.AddConnection(selectedNodes[0], selectedNodes[1]);
                    
                });

                menu.ShowAsContext();
                e.Use(); // verhindert, dass Unity sein eigenes Menü anzeigt
            }
        }
    }

    [CustomEditor(typeof(GameManager))]
    public class GameManagerEditor : Editor
    {
        int clickedConIdx = -1;

        // Custom Inspector
        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();

            GameManager gm = (GameManager)target;

            GUILayout.Label("Generation Parameters", EditorStyles.boldLabel);

            EditorGUI.BeginChangeCheck();
            gm.nodeCount = EditorGUILayout.IntSlider("Node Count", gm.nodeCount, 0, 200);
            if (EditorGUI.EndChangeCheck() && gm.regenerateOnChange)
            {
                gm.GenerateAlongSphere();
                gm.GenerateConnections();
                SceneView.RepaintAll();
            }

            EditorGUI.BeginChangeCheck();
            gm.minConnectionLength = EditorGUILayout.Slider("Min Connection Length", gm.minConnectionLength, 0, gm.maxConnectionLength);
            gm.maxConnectionLength = EditorGUILayout.Slider("Max Connection Length", gm.maxConnectionLength, gm.minConnectionLength, 30);
            if (EditorGUI.EndChangeCheck() && gm.regenerateOnChange)
            {
                gm.GenerateConnections();
                SceneView.RepaintAll();
            }

            GUILayout.Space(10);
            GUILayout.Label("Connection Gizmos", EditorStyles.boldLabel);

            gm.hoverRadiusCon = EditorGUILayout.IntSlider("Hover Radius (Connection)", gm.hoverRadiusCon, 0, 100);
            gm.hoverRadiusNode = EditorGUILayout.IntSlider("Hover Radius (Node)", gm.hoverRadiusNode, 0, 100);




            GUILayout.BeginHorizontal();

            if (GUILayout.Button("Distribute Nodes"))
            {
                gm.GenerateAlongSphere();
                SceneView.RepaintAll();
            }

            if (GUILayout.Button("Generate Connections"))
            {
                gm.GenerateConnections();
                SceneView.RepaintAll();
            }

            if (GUILayout.Button("Generate Both"))
            {
                gm.GenerateAlongSphere();
                gm.GenerateConnections();
                SceneView.RepaintAll();
            }

            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();

            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();

            GUILayout.BeginVertical();
            for (int i = 0; i < gm.levels.Count; i++)
            {
                if (gm.selectedLevel == i)
                    GUILayout.Label("▷ Level " + i, EditorStyles.boldLabel);
                else
                    GUILayout.Label("  Level " + i);
            }
            GUILayout.EndVertical();

            GUILayout.BeginVertical();
            for (int i = 0; i < gm.levels.Count; i++)
            {
                if (GUILayout.Button("Load"))
                    gm.LoadLevelData(i);
            }
            GUILayout.EndVertical();

            GUILayout.BeginVertical();
            for (int i = 0; i < gm.levels.Count; i++)
            {
                GUILayout.BeginHorizontal();
                if (gm.selectedLevel == i)
                    if (GUILayout.Button("Save"))
                        gm.SaveLevelData(i);

                if (GUILayout.Button("Delete"))
                {
                    gm.levels.Remove(gm.levels[i]);
                    if (gm.selectedLevel == i)
                        gm.selectedLevel = -1;
                    if (gm.selectedLevel > i)
                        gm.selectedLevel--;
                    if (gm.levels.Count <= 0)
                        gm.selectedLevel = -1;
                }
                GUILayout.EndHorizontal();
            }
            GUILayout.EndVertical();

            GUILayout.EndHorizontal();

            if (GUILayout.Button("Save as new"))
                gm.SaveLevelData();

            GUILayout.Space(20);

            if (GUILayout.Button("Execute Round End"))
                gm.ExecuteRoundEnd();

        }

        // Custom Scene Interaction while GameManager selected
        private void OnSceneGUI()
        { 
            Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;

            GameManager gm = FindFirstObjectByType<GameManager>();
            if (gm == null) return;

            var nodes = gm.GetNodes();
            var connections = gm.GetConnections();

            GameObject selected = Selection.activeGameObject;
            bool allowHover = false;

            if (selected == gm.gameObject)
                allowHover = true;
            else
            {
                Node node = selected?.GetComponent<Node>();
                if (node != null && nodes.Contains(node))
                    allowHover = true;
            }

            if (!allowHover) return;

            if (connections == null || connections.Count == 0) return;
            Camera cam = SceneView.lastActiveSceneView.camera;
            if (cam == null) return;

            Vector2 mouse = Event.current.mousePosition;
            mouse.y = cam.pixelHeight - mouse.y;
            Vector3 mousePos = new Vector3(mouse.x, mouse.y, 0);

            int closestIdx = -1;
            float closestDist = float.MaxValue;
            bool cancelHover = false;

            // Hover-Ermittlung Connections
            for (int i = 0; i < connections.Count; i++)
            {
                connections[i].hovered = false;

                if (cancelHover)
                    continue;

                var con = connections[i];
                Vector3 a = cam.WorldToScreenPoint(con.nodeA.transform.position);
                Vector3 b = cam.WorldToScreenPoint(con.nodeB.transform.position);

                Vector3 ab = b - a;
                Vector3 am = mousePos - a;
                float t = Mathf.Clamp01(Vector3.Dot(am, ab) / ab.sqrMagnitude);
                Vector3 proj = a + t * ab;
                float dist = Vector3.Distance(mousePos, proj);

                if (Vector3.Distance(a, mousePos) <= gm.hoverRadiusNode || Vector3.Distance(b, mousePos) <= gm.hoverRadiusNode)
                    cancelHover = true;

                if (dist < closestDist && dist < gm.hoverRadiusCon)
                {
                    closestDist = dist;
                    closestIdx = i;
                }
            }

            if (closestIdx < 0)
                cancelHover = true;


            if (!cancelHover)
                connections[closestIdx].hovered = true;


            // Klick-Behandlung
            Event e = Event.current;


            if (e.type == EventType.MouseDown && e.button == 0 && !cancelHover)
            {
                clickedConIdx = closestIdx;
            }

            if (e.type == EventType.MouseUp && e.button == 0)
            {
                if (closestIdx == clickedConIdx && !cancelHover)
                {
                    connections[closestIdx].allowed = !connections[closestIdx].allowed;
                    e.Use(); // Event als verarbeitet markieren
                }

                clickedConIdx = -1;
            }

            // SceneView kontinuierlich aktualisieren
            SceneView.RepaintAll();
        }
    }
}
