// Copyright (c) 2026 EzAdmin. All rights reserved.
// Licensed under the EzAdmin Client License. See LICENSE-CLIENT.txt.

using System.Collections.Generic;
using System.IO;
using EzAdmin.Client;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;

namespace EzAdmin.EditorTools
{
    public static class EzAdminScenes
    {
        public sealed class Choice
        {
            public string Name;
            public string Path;
            public bool InBuild;
        }

        public static List<Choice> All(string skipPath)
        {
            var list = new List<Choice>();
            var seen = new HashSet<string>();
            foreach (var s in EditorBuildSettings.scenes)
            {
                if (string.IsNullOrEmpty(s.path) || s.path == skipPath || !File.Exists(s.path)) continue;
                list.Add(new Choice { Name = System.IO.Path.GetFileNameWithoutExtension(s.path), Path = s.path, InBuild = s.enabled });
                seen.Add(s.path);
            }
            foreach (string guid in AssetDatabase.FindAssets("t:Scene", new[] { "Assets" }))
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                if (seen.Contains(path) || path == skipPath || path.StartsWith("Assets/EzAdmin")) continue;
                list.Add(new Choice { Name = System.IO.Path.GetFileNameWithoutExtension(path), Path = path, InBuild = false });
            }
            return list;
        }

        public static string[] Labels(List<Choice> choices, string first)
        {
            var labels = new string[choices.Count + 1];
            labels[0] = first;
            for (int i = 0; i < choices.Count; i++)
                labels[i + 1] = choices[i].InBuild ? choices[i].Name : "Other scenes/" + choices[i].Name + "  (adds it to the build)";
            return labels;
        }

        public static void AddToBuild(string path)
        {
            var scenes = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes);
            int at = scenes.FindIndex(s => s.path == path);
            if (at >= 0)
            {
                if (!scenes[at].enabled) scenes[at] = new EditorBuildSettingsScene(path, true);
            }
            else
            {
                scenes.Add(new EditorBuildSettingsScene(path, true));
            }
            EditorBuildSettings.scenes = scenes.ToArray();
        }
    }

    [CustomEditor(typeof(EzAdminLoadingScreen))]
    public sealed class EzAdminLoadingScreenInspector : EzAdminInspector
    {
        protected override string Title => "Loading screen";
        protected override string Blurb => "Signs the player in, loads their items, then opens your game. Change the name, logo and colours below.";

        protected override string Status(out Color colour)
        {
            var scenes = EditorBuildSettings.scenes;
            string here = ((EzAdminLoadingScreen)target).gameObject.scene.path;
            if (scenes.Length == 0 || scenes[0].path != here)
            {
                colour = Amber;
                return "Not first in Build Settings";
            }
            colour = EzAdminBrand.Green;
            return Application.isPlaying ? "Showing" : "Plays first";
        }

        protected override bool OpenByDefault(string title)
        {
            return title == "Your game" || title == "Colours" || title == "Where it shows";
        }

        protected override bool ShowGroup(string title)
        {
            if (title != "VR") return true;
            var mode = serializedObject.FindProperty("_mode");
            return mode == null || mode.enumValueIndex != (int)EzAdminLoadingScreen.ScreenMode.Flat;
        }

        protected override bool DrawField(SerializedProperty prop)
        {
            if (prop.name == "_mode")
            {
                string[] names = { "Automatic (VR on a headset, full screen elsewhere)", "VR only", "Flat screen only" };
                prop.enumValueIndex = EditorGUILayout.Popup(new GUIContent("Show as", prop.tooltip), prop.enumValueIndex, names);
                return true;
            }
            return DrawScene(prop);
        }

        protected override void Extras()
        {
            var screen = (EzAdminLoadingScreen)target;
            if (!Application.isPlaying)
            {
                GUILayout.Space(2);
                if (!screen.HasDesign)
                {
                    EditorGUILayout.HelpBox("The screen is not in this scene yet. Build it once and every part shows up " +
                                            "under 'Loading Screen' in the Hierarchy, ready to move and restyle.", MessageType.Info);
                    if (GUILayout.Button("Build the loading screen into this scene", GUILayout.Height(26)))
                        EzAdminLoadingSceneMaker.BuildDesign(screen);
                }
                else
                {
                    GUILayout.BeginHorizontal();
                    if (GUILayout.Button("Select the screen objects", GUILayout.Height(22)))
                        Selection.activeGameObject = GameObject.Find("Loading Screen");
                    if (GUILayout.Button("Rebuild the screen", GUILayout.Height(22))
                        && EditorUtility.DisplayDialog("EzAdmin", "Build the screen again with the newest EzAdmin design? " +
                                                       "Changes you made to the screen objects by hand are replaced. Your " +
                                                       "settings below are kept.", "Rebuild", "Cancel"))
                        EzAdminLoadingSceneMaker.BuildDesign(screen);
                    GUILayout.EndHorizontal();
                }
            }
            string here = screen.gameObject.scene.path;
            var scenes = EditorBuildSettings.scenes;
            if (string.IsNullOrEmpty(here) || (scenes.Length > 0 && scenes[0].path == here)) return;
            GUILayout.Space(2);
            if (GUILayout.Button("Make this the first scene in Build Settings", GUILayout.Height(24)))
            {
                var list = new List<EditorBuildSettingsScene>(scenes);
                list.RemoveAll(s => s.path == here);
                list.Insert(0, new EditorBuildSettingsScene(here, true));
                EditorBuildSettings.scenes = list.ToArray();
            }
        }

        private bool DrawScene(SerializedProperty prop)
        {
            if (prop.name != "_nextScene") return false;
            string here = ((EzAdminLoadingScreen)target).gameObject.scene.path;
            var choices = EzAdminScenes.All(here);
            var labels = EzAdminScenes.Labels(choices, "The next scene in Build Settings");
            int current = 0;
            for (int i = 0; i < choices.Count; i++)
                if (choices[i].Name == prop.stringValue) current = i + 1;
            int picked = EditorGUILayout.Popup(new GUIContent("Open after loading", prop.tooltip), current, labels);
            if (picked != current)
            {
                if (picked == 0)
                {
                    prop.stringValue = "";
                }
                else
                {
                    var choice = choices[picked - 1];
                    prop.stringValue = choice.Name;
                    if (!choice.InBuild) EzAdminScenes.AddToBuild(choice.Path);
                }
            }
            if (!string.IsNullOrEmpty(prop.stringValue) && current == 0)
                EditorGUILayout.HelpBox("The scene '" + prop.stringValue + "' was not found. Pick one from the list.", MessageType.Warning);
            return true;
        }
    }
}
