﻿using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace RKOKO.Config.Free.Editor
{
    public class ToolEditor
    {
        [MenuItem("RKOKO Config Free/Install", priority = 200)]
        public static void Install()
        {
            Action next = () =>
            {
                if (!Directory.Exists(Paths.TABLE_DIR))
                {
                    Directory.CreateDirectory(Paths.TABLE_DIR);
                    var demoXlsxSource = Path.Combine(Paths.DEMO_ROOT,
                        $"demo_{EditorLocalize.GetLanguageType().ToString()}.xlsx");
                    if (!File.Exists(demoXlsxSource))
                    {
                        ShowMessageBox(
                            $"{EditorLocalize.Get(1058)}\n" +
                            $"{EditorLocalize.Get(1059)}"
                        );
                        return;
                    }

                    var dest = Path.Combine(Paths.TABLE_DIR,
                        Path.GetFileName(demoXlsxSource));
                    File.Copy(demoXlsxSource, dest, true);
                }

                ShowMessageBox(EditorLocalize.Get(1008), EditorLocalize.Get(1009), OpenTablesFolder);
            };
            if (!IsNewtonsoftJsonAvailable())
            {
                NewtonsoftJsonInstaller.InstallNewtonsoftJson((success, msg) =>
                {
                    if (success)
                    {
                        next?.Invoke();
                    }
                    else
                    {
                        ShowMessageBox(msg);
                    }
                });
            }
            else
            {
                next?.Invoke();
            }
        }

        [MenuItem("RKOKO Config Free/Install", true)]
        public static bool ExecuteInstallValidate()
        {
            return !IsInstall();
        }

        [MenuItem("RKOKO Config Free/Open Backup Folder", priority = 502)]
        public static void OpenBackupFolder()
        {
            if (Directory.Exists(Paths.BACK_UP_FOLDER))
            {
                var directories = Directory.GetDirectories(Paths.BACK_UP_FOLDER, "*", SearchOption.TopDirectoryOnly)
                    .ToList();
                if (directories.Count > 0)
                {
                    EditorUtility.RevealInFinder(Path.GetFullPath(directories.First()));
                    return;
                }
            }

            ShowMessageBox(EditorLocalize.Get(1035));
        }

        [MenuItem("RKOKO Config Free/Open Backup Folder", true)]
        public static bool OpenBackupFolderValidate()
        {
            return IsInstall();
        }


        [MenuItem("RKOKO Config Free/Open Tables Folder", priority = 401)]
        public static void OpenTablesFolder()
        {
            if (!File.Exists(Paths.TABLE_MD_FILE))
            {
                File.WriteAllText(Paths.TABLE_MD_FILE, string.Empty);
            }

            EditorUtility.RevealInFinder(Path.GetFullPath(Paths.TABLE_MD_FILE));
        }

        [MenuItem("RKOKO Config Free/Open Tables Folder", true)]
        public static bool OpenTablesFolderValidate()
        {
            return IsInstall();
        }

        [MenuItem("RKOKO Config Free/Open Plain JSON", priority = 501)]
        public static void OpenPlainJson()
        {
            var json = Path.Combine(Paths.OUTPUT_DIR, "json/all_in_one.json");
            if (!File.Exists(json))
            {
                ShowMessageBox(EditorLocalize.GetFormat(1032, json));
                return;
            }

            Application.OpenURL(new Uri(Path.GetFullPath(json)).AbsoluteUri);
        }

        [MenuItem("RKOKO Config Free/Open Plain JSON", true)]
        public static bool OpenPlainJsonValidate()
        {
            return IsInstall();
        }


        [MenuItem("RKOKO Config Free/Export", priority = 402)]
        public static void Export()
        {
            new Exporter().Export();
        }

        [MenuItem("RKOKO Config Free/Export", true)]
        public static bool ExportValidate()
        {
            return IsInstall();
        }

        [MenuItem("RKOKO Config Free/Documentation", priority = 301)]
        public static void OpenDocumentation()
        {
            Application.OpenURL(new Uri(Path.GetFullPath(Paths.DOCUMENTATION_INDEX_HTML)).AbsoluteUri);
        }


        public static string ToUnityPath(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                return string.Empty;
            try
            {
                string assetsFullPath = Path.GetFullPath(Application.dataPath)
                    .Replace('\\', '/')
                    .TrimEnd('/');
                string targetFullPath = Path.GetFullPath(path)
                    .Replace('\\', '/')
                    .TrimEnd('/');
                if (targetFullPath.Equals(assetsFullPath, StringComparison.Ordinal))
                    return "Assets";
                if (targetFullPath.StartsWith(assetsFullPath + "/", StringComparison.Ordinal))
                    return "Assets" + targetFullPath.Substring(assetsFullPath.Length);
                return string.Empty;
            }
            catch
            {
                return string.Empty;
            }
        }

        public static bool IsNewtonsoftJsonAvailable()
        {
            return GetTypeOrDefault("Newtonsoft.Json.JsonConvert") != null;
        }

        public static Type GetTypeOrDefault(string fullName)
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                var type = assembly.GetType(fullName);
                if (type != null)
                {
                    return type;
                }
            }

            return null;
        }

        public static bool IsInstall() => Directory.Exists(Paths.TABLE_DIR) && IsNewtonsoftJsonAvailable();

        public static void ShowMessageBox(string message, string btnOk, Action onOk = null)
        {
            if (EditorUtility.DisplayDialog(EditorLocalize.Get(1007), message, btnOk))
            {
                onOk?.Invoke();
            }
        }

        public static void ShowMessageBox(string message, Action onOk = null)
        {
            if (EditorUtility.DisplayDialog(EditorLocalize.Get(1007), message, EditorLocalize.Get(1010)))
            {
                onOk?.Invoke();
            }
        }

        public static void CreateDirIfNotExists(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return;
            }

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }


        public static void Ping(string path)
        {
            var unityPath = ToUnityPath(path);
            if (string.IsNullOrEmpty(unityPath))
                return;
            var obj = AssetDatabase.LoadAssetAtPath<Object>(unityPath);
            Ping(obj);
        }

        public static void Ping(Object target)
        {
            if (target == null)
                return;
            EditorApplication.ExecuteMenuItem("Window/General/Project");
            EditorGUIUtility.PingObject(target);
        }
    }
}