using System;
using Intrepid.Diagnostics;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Editor.GON.StageEditor.Baker
{
    namespace Editor.GardensStageEditor
    {
        public static class StageBaker
        {
            private const string GeneratedRootName = "Generated";

            public static GameObject Bake(StageDefinition stage, PrefabTable prefabTable)
            {
                stage.EnsureDefaults();

                var scene = SceneManager.GetSceneByName(stage.stageTag.SceneName);
                var isSceneLoaded = scene.isLoaded;
                if (!isSceneLoaded)
                {
                    scene = EditorSceneManager.OpenScene(scene.path, OpenSceneMode.Additive);
                }
                var generatedRoot = EnsureGeneratedRoot(scene);
                Undo.RegisterCreatedObjectUndo(generatedRoot, "Create Generated Root");
                var stageRoot = EnsureStageRoot(stage, generatedRoot);
                StageBuilder.BuildStage(new StageBuilderRequest
                {
                    Stage = stage,
                    Root = stageRoot,
                    PrefabTable = prefabTable
                });
                Undo.RegisterCreatedObjectUndo(stageRoot, "Create Stage Root");
                
                EditorSceneManager.MarkSceneDirty(scene);
                if (isSceneLoaded)
                {
                    Selection.activeGameObject = stageRoot;
                }
                else
                {
                    EditorSceneManager.SaveScene(scene);
                    EditorSceneManager.CloseScene(scene, false);
                }

                DLogger.LogDebug($"Bake started for stage '{stage.Id}'. State root is ready.");
                
                return stageRoot;
            }

            private static GameObject EnsureStageRoot(StageDefinition stage, GameObject generatedRoot)
            {
                foreach (Transform goTransform in generatedRoot.transform)
                {
                    if (goTransform.gameObject.name == stage.Id)
                    {
                        goTransform.gameObject.name = $"{goTransform.gameObject.name}_bkp";
                        goTransform.gameObject.SetActive(false);
                    }
                }
                
                var go = new GameObject(stage.Id);
                go.transform.SetParent(generatedRoot.transform);
                return go;
            }

            private static GameObject EnsureGeneratedRoot(Scene scene)
            {
                foreach (var gameObject in scene.GetRootGameObjects())
                {
                    if (gameObject.name == GeneratedRootName)
                    {
                        return gameObject;
                    }
                }

                return new GameObject(GeneratedRootName);
            }
        }
    }
}