using UnityEditor;
using UnityEngine.Tilemaps;
using UnityEngine;
using System.IO;
using UnityEditor.SceneManagement;

namespace GatherAndDefend.LevelEditor
{
    [CustomEditor(typeof(LevelEditor))]
    public class LevelEditorCustomInspector : Editor
    {
        const string defaultName = "Level";
        const string extension = ".asset";

        string _infoText = string.Empty;
        public override void OnInspectorGUI()
        {
            EditorGUILayout.HelpBox(@"How to use : 
- Path : you can optionally assign a folder in order to change the path to which the Level files will be created and saved
- Level : the level file you're currently working on (for saving and loading purposes).
- Create button : creates an empty level at given path, and assign it to the Level field in inspector.
- Save button : saves all scene tilemaps' contents to the assigned level file.
- Load button : iterates through all scene tilemaps and fills them according to what data can be found in the level file.

Important considerations : 
- the save and load buttons won't work if there is no Level assigned.", MessageType.None);

            DrawDefaultInspector();
            if (GUILayout.Button(nameof(Create)))
            {
                Create();
            }
            if (GUILayout.Button(nameof(Save)))
            {
                Save();
            }
            if (GUILayout.Button(nameof(Load)))
            {
                Load();
            }

            if (_infoText != string.Empty)
            {
                EditorGUILayout.HelpBox(_infoText, MessageType.Error);
            }
        }
        private string GetPath()
        {
            var targ = (LevelEditor)target;
            var asset = EditorGUILayout.ObjectField(targ.Path, typeof(DefaultAsset), false);
            if (!asset) return "Assets";
            
            return AssetDatabase.GetAssetPath(asset);
        }
        private void Create()
        {
            string path = GetPath();
            if (!Directory.Exists(path))
            {
                _infoText = "the object assigned to Path is not a directory!";
            }
            LevelEditor targ = (LevelEditor)target;
            _infoText = string.Empty;
            string name = defaultName;
            
            if (File.Exists(path + "/" + name + extension))
            {
                var i = 0;
                while (File.Exists(path + "/" + name + i + extension)) i++;
                name += i;
            }

            var map = CreateInstance<Level>();
            map.name = name;
            AssetDatabase.CreateAsset(map, path + "/" + name + extension);
            targ.Level = map;
        }
        private void Save()
        {
            string path = GetPath();
            if (!Directory.Exists(path))
            {
                _infoText = "the object assigned to Path is not a directory!";
                return;
            }

            LevelEditor targ = (LevelEditor)target;
            if (!targ.Level)
            {
                _infoText = "no level to save to. please assign the Level field in the inspector.";
                return;
            }
            string name = targ.Level.name;
            var map = CreateInstance<Level>();
            map.name = name;

            foreach (Tilemap tilemap in targ.GetComponentsInChildren<Tilemap>())
            {
                map.SaveFromTilemap(tilemap);
            }

            AssetDatabase.CreateAsset(map, path + "/" + name + extension);
            targ.Level = map;
            _infoText = string.Empty;
        }
        private void Load()
        {
            var targ = (LevelEditor)target;
            if (!targ.Level)
            {
                _infoText = "no level to save to. please assign the Level field in the inspector.";
                return;
            }

            while (targ.transform.childCount > 0)
            {
                DestroyImmediate(targ.transform.GetChild(0).gameObject);
            }

            foreach (TilemapData tilemapData in targ.Level)
            {
                var tilemap = new GameObject(tilemapData.Key).AddComponent<Tilemap>();
                tilemap.tileAnchor = Vector3.zero;
                tilemap.gameObject.AddComponent<TilemapRenderer>();
                tilemap.transform.SetParent(targ.transform);
                tilemapData.LoadToTilemapEditor(tilemap);
            }
            _infoText = string.Empty;
            EditorSceneManager.MarkAllScenesDirty();
        }
    }
    
}