/*           INFINITY CODE          */
/*     https://infinity-code.com    */

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

namespace InfinityCode.TreeTools.Editors
{
    [InitializeOnLoad]
    public class Prefs: EditorWindow
    {
        public const string PREFIX = "TreeTool_";
        private const int HEIGHT = 110;

        public static Pref<bool> createUndo = false;
        public static Pref<float> selectionDistance = 50;
        public static Pref<float> selectionSize = 1;
        public static Pref<bool> snapToTerrain = true;

        private static Prefs instance;

        static Prefs()
        {
            EditorApplication.delayCall += () => Load();
        }

        private static void InitWindowStyle(Prefs wnd)
        {
            VisualElement ve = wnd.rootVisualElement;
            IStyle style = ve.style;
            style.borderBottomColor = Color.black;
            style.borderBottomWidth = 1;
            style.borderLeftColor = Color.black;
            style.borderLeftWidth = 1;
            style.borderRightColor = Color.black;
            style.borderRightWidth = 1;
            style.borderTopColor = Color.black;
            style.borderTopWidth = 1;
            style.paddingBottom = 2;
            style.paddingLeft = 2;
            style.paddingRight = 2;
            style.paddingTop = 2;
        }

        private static void Load()
        {
            FieldInfo[] fields = typeof(Prefs).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            
            foreach (FieldInfo field in fields)
            {
                if (!field.FieldType.IsSubclassOf(typeof(Pref))) continue;

                Pref pref = field.GetValue(null) as Pref;
                if (pref == null) continue;

                pref.path = PREFIX + field.Name;
                pref.Load();
            }
        }

        private void OnDestroy()
        {
            instance = null;
        }

        private void OnGUI()
        {
            if (focusedWindow != this) Close();

            Event e = Event.current;

            if (e.type == EventType.KeyDown)
            {
                if (e.keyCode == KeyCode.Escape || e.keyCode == KeyCode.Return || e.keyCode == KeyCode.KeypadEnter)
                {
                    e.Use();
                    Close();
                    return;
                }
            }

            createUndo.Set(EditorGUILayout.Toggle("Create Undo", createUndo));
            if (createUndo)
            {
                EditorGUILayout.HelpBox("Creating undo can cause temporary editor freezes.", MessageType.Warning);
                if (Math.Abs(position.height - (HEIGHT + 40)) > float.Epsilon)
                {
                    Rect r = position;
                    r.height = HEIGHT + 40;
                    position = r;
                }
            }
            else if (Math.Abs(position.height - HEIGHT) > float.Epsilon)
            {
                Rect r = position;
                r.height = HEIGHT;
                position = r;
            }
            
            EditorGUI.BeginChangeCheck();
            selectionDistance.Set(EditorGUILayout.IntSlider("Selection Distance", (int)selectionDistance, 1, 200));
            if (EditorGUI.EndChangeCheck())
            {
                TreeTool.ResetVisibleItems();
                SceneView.RepaintAll();
            }

            EditorGUI.BeginChangeCheck();
            selectionSize.Set(EditorGUILayout.Slider("Selection Size", selectionSize, 0.1f, 2f));
            if (EditorGUI.EndChangeCheck()) SceneView.RepaintAll();

            EditorGUI.BeginChangeCheck();
            snapToTerrain.Set(EditorGUILayout.Toggle("Snap To Terrain", snapToTerrain));
            if (EditorGUI.EndChangeCheck())
            {
                TreeItem item = TreeTool.activeItem;
                if (item != null)
                {
                    Vector3 pos = item.position;
                    pos.y = item.SnapY(pos);
                    item.SetPosition(pos);
                }
            }

            EditorGUILayout.BeginHorizontal();

            EditorGUILayout.Space();
            if (GUILayout.Button("Close", GUILayout.ExpandWidth(false)))
            {
                Close();
            }

            EditorGUILayout.EndHorizontal();
        }

        [MenuItem(MenuItems.MENU_PATH + "Settings", false, MenuOrder.SETTINGS)]
        public static void Open()
        {
            Prefs wnd = GetWindow<Prefs>("Tree Tool Settings");
            wnd.minSize = Vector2.one;
            Rect rect = wnd.position;
            rect.size = new Vector2(300, HEIGHT);
            wnd.position = rect;
            wnd.ShowPopup();
            wnd.Focus();
        }

        public static Prefs Open(Vector2 position)
        {
            Prefs wnd = CreateInstance<Prefs>();

            InitWindowStyle(wnd);

            instance = wnd;
            wnd.titleContent = new GUIContent("Settings");
            Vector2 pos = GUIUtility.GUIToScreenPoint(position);
            Vector2 size = new Vector2(300, HEIGHT);
            pos.x -= size.x / 2;
            Rect rect = new Rect(pos, size);

            wnd.minSize = Vector2.one;
            wnd.position = rect;
            wnd.ShowPopup();
            wnd.Focus();

            return wnd;
        }
    }
}