﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace RKOKO.Config.Free.Editor
{
    public class EditorLocalize
    {
        public static readonly Dictionary<LanguageType, string> DisplayNames = new Dictionary<LanguageType, string>()
        {
            { LanguageType.ZhHans, "简体中文" },
            { LanguageType.ZhHant, "繁體中文" },
            { LanguageType.En, "English" },
            { LanguageType.Ja, "日本語" },
            { LanguageType.Ko, "한국어" },
            { LanguageType.Es, "Español" },
            { LanguageType.Ru, "Русский" },
            { LanguageType.Fr, "Français" },
            { LanguageType.De, "Deutsch" },
            { LanguageType.Pt, "Português" },
            { LanguageType.Vi, "Tiếng Việt" },
            { LanguageType.Tr, "Türkçe" },
            { LanguageType.Pl, "Polski" },
            { LanguageType.It, "Italiano" },
            { LanguageType.Th, "ไทย" },
        };

        private const string EDITOR_KEY_RKOKO_CONFIG_LAN = "EDITOR_KEY_RKOKO_CONFIG_LAN";


        private static LocalizeData _localizeData = null;

        private static LocalizeData LocalizeData
        {
            get
            {
                if (_localizeData == null)
                {
                    _localizeData = LocalizeData.FromJson(LoadJson());
                    foreach (var item in _localizeData.data)
                    {
                        item.localizeValues = item.localizeValues
                            .Select(DecodeLocalizeText)
                            .ToList();
                    }
                }

                return _localizeData;
            }
        }

        private static string LoadJson()
        {
            var textAsset =
                AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/RKOKOConfigTableToolFree/Editor/localize.json");
            if (textAsset == null)
            {
                throw new Exception("File not found: Assets/RKOKOConfigTableToolFree/Editor/localize.json");
            }

            return textAsset.text;
        }

        private static LanguageType CurrentLanguage => GetLanguageType();

        public static string Get(int key)
        {
            return LocalizeData.Get(CurrentLanguage, key);
        }

        public static string GetFormat(int key, params string[] args)
        {
            var valueString = LocalizeData.Get(CurrentLanguage, key);
            if (string.IsNullOrEmpty(valueString))
            {
                return string.Empty;
            }

            if (args == null || args.Length == 0)
            {
                return valueString;
            }

            foreach (var arg in args)
            {
                var replaceValue = arg ?? string.Empty;
                var index = valueString.IndexOf("%s", StringComparison.Ordinal);
                if (index < 0)
                {
                    break;
                }

                valueString = valueString.Remove(index, 2).Insert(index, replaceValue);
            }

            return valueString;
        }


        public static LanguageType GetLanguageType()
        {
            if (EditorPrefs.HasKey(EDITOR_KEY_RKOKO_CONFIG_LAN))
            {
                var value = EditorPrefs.GetInt(EDITOR_KEY_RKOKO_CONFIG_LAN);
                if (Enum.IsDefined(typeof(LanguageType), value))
                {
                    return (LanguageType)value;
                }
            }

            var language = GetLanguageFollowSystem();
            EditorPrefs.SetInt(EDITOR_KEY_RKOKO_CONFIG_LAN, (int)language);
            return language;
        }

        private static LanguageType GetLanguageFollowSystem()
        {
            switch (Application.systemLanguage)
            {
                case SystemLanguage.French:
                    return LanguageType.Fr;
                case SystemLanguage.German:
                    return LanguageType.De;
                case SystemLanguage.Italian:
                    return LanguageType.It;
                case SystemLanguage.Japanese:
                    return LanguageType.Ja;
                case SystemLanguage.Korean:
                    return LanguageType.Ko;
                case SystemLanguage.Polish:
                    return LanguageType.Pl;
                case SystemLanguage.Portuguese:
                    return LanguageType.Pt;
                case SystemLanguage.Russian:
                case SystemLanguage.Belarusian:
                    return LanguageType.Ru;
                case SystemLanguage.Spanish:
                    return LanguageType.Es;
                case SystemLanguage.Thai:
                    return LanguageType.Th;
                case SystemLanguage.Turkish:
                    return LanguageType.Tr;
                case SystemLanguage.Vietnamese:
                    return LanguageType.Vi;
                case SystemLanguage.ChineseTraditional:
                    return LanguageType.ZhHant;
                case SystemLanguage.ChineseSimplified:
                case SystemLanguage.Chinese:
                    return LanguageType.ZhHans;
                default:
                    return LanguageType.En;
            }
        }

        public static string GetDisplayName()
        {
            if (DisplayNames.TryGetValue(GetLanguageType(), out var displayName))
            {
                return displayName;
            }

            return string.Empty;
        }

        public static void ChangeLanguage(LanguageType language)
        {
            EditorPrefs.SetInt(EDITOR_KEY_RKOKO_CONFIG_LAN, (int)language);
        }

        public static void SetToNull()
        {
            _localizeData = null;
        }


        private static string DecodeLocalizeText(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }

            const string placeholder = "__RKOKO_ESCAPED_NEWLINE__";

            // 先保护 \\n，让它不要被下面的 \n 替换误伤
            text = text.Replace("\\\\n", placeholder);

            // 再把 \n 转成真正换行
            text = text.Replace("\\n", "\n");

            // 最后把被保护的内容还原成字面量 \n
            text = text.Replace(placeholder, "\\n");
            return text;
        }
    }
}