using System;
using System.Collections.Generic;
using System.Linq;
using NBC.Asset;
using Newtonsoft.Json.Linq;
using UnityEngine;

namespace NBC
{
    public class LanguageManager
    {
        private string _currentCustomLanguageName = string.Empty;
        private SystemLanguage _currentLanguage;

        private Dictionary<int, ILanguage> _lanModuleDic = new Dictionary<int, ILanguage>();


        /// <summary>
        /// 变化通知事件
        /// </summary>
        public event Action ChangeAction;

        public LanguageManager()
        {
            LoadLanguageConfig();
        }

        public void AddLanguageModule(int type, ILanguage languageModule)
        {
            _lanModuleDic.Add(type, languageModule);
        }

        public ILanguage GetLanguageModule(int type)
        {
            return _lanModuleDic.GetValueOrDefault(type);
        }

        public string GetCurrentCustomLanguageName()
        {
            return _currentCustomLanguageName;
        }

        public SystemLanguage GetCurrentLanguage()
        {
            return _currentLanguage;
        }

        public void AutoUseLanguage()
        {
            SystemLanguage language = Application.systemLanguage;
            if (PlayerPrefs.HasKey(LanguageConst.LanguageSaveKey))
            {
                var value = PlayerPrefs.GetInt(LanguageConst.LanguageSaveKey, -1);
                if (value >= 0)
                {
                    language = (SystemLanguage)value;
                }
            }

            var list = LanguageConst.languageMap.Values.ToList();
            var findLan = list.FindIndex(t => t.Language == language);
            if (findLan < 0)
            {
                language = SystemLanguage.English;
            }

            UseLanguage(language);
        }

        public void UseLanguage(SystemLanguage language)
        {
            _currentLanguage = language;
            if (LanguageConst.languageMap.TryGetValue(language, out var info))
            {
                _currentCustomLanguageName = info.Code;
            }

            foreach (var value in _lanModuleDic.Values)
            {
                value.UseLanguage(language);
            }

            ChangeAction?.Invoke();
        }

        public void AddLanguage(SystemLanguage language, bool isDefault = false)
        {
            foreach (var pair in _lanModuleDic)
            {
                pair.Value.AddLanguage(language);
            }

            if (isDefault)
            {
                UseLanguage(language);
            }
        }

        #region config

        private readonly Dictionary<string, LanguageConfig> _languageConfigs = new Dictionary<string, LanguageConfig>();
        private readonly Dictionary<string, string> _font2Key = new Dictionary<string, string>();

        private readonly Dictionary<string, LanguageConfig> _languageFontConfigs =
            new Dictionary<string, LanguageConfig>();

        private readonly Dictionary<string, LanguageConfig> _languageImagesConfigs =
            new Dictionary<string, LanguageConfig>();

        public Dictionary<string, string> GetLanguageConfig(LanguageInfo languageInfo)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            foreach (var key in _languageConfigs.Keys)
            {
                var value = _languageConfigs[key];
                dic[key] = value[languageInfo.Code];
            }

            return dic;
        }

        public Dictionary<string, LanguageFontConfig> GetLanguageFontConfig(LanguageInfo languageInfo)
        {
            if (_font2Key.Count != _languageFontConfigs.Count)
            {
                foreach (var fKey in _languageFontConfigs.Keys)
                {
                    var config = _languageFontConfigs[fKey];
                    foreach (var key in config.Keys)
                    {
                        var result = config[key];
                        if (result != null)
                        {
                            string[] strs = result.Split(",");
                            _font2Key[strs[1]] = fKey;
                        }
                    }
                }
            }

            Dictionary<string, LanguageFontConfig> dic = new Dictionary<string, LanguageFontConfig>();
            foreach (var key in _languageFontConfigs.Keys)
            {
                var config = _languageFontConfigs[key];
                string result = config[languageInfo.Code];
                if (result != null)
                {
                    string[] strs = result.Split(",");
                    var result2 = new LanguageFontConfig()
                    {
                        Type = strs[0],
                        Name = key,
                        RelativePath = strs[1],
                    };
                    dic[key] = result2;
                }
            }

            return dic;
        }


        public Dictionary<string, string> GetLanguageImageConfig(LanguageInfo languageInfo)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            foreach (var key in _languageImagesConfigs.Keys)
            {
                var value = _languageImagesConfigs[key];
                dic[key] = value[languageInfo.Code];
            }

            return dic;
        }

        public Dictionary<string, string> GetFont2KeyDic()
        {
            return _font2Key;
        }

        private void LoadLanguageConfig()
        {
            _languageConfigs.Clear();
            var textAsset = Assets.Load<TextAsset>("Config/language");
            if (textAsset)
            {
                var jToken = JObject.Parse(textAsset.text);
                foreach (var obj in jToken)
                {
                    switch (obj.Key)
                    {
                        case "language":
                            LoadLanguageConfig(obj.Value, _languageConfigs);
                            break;
                        case "languageFont":
                            LoadLanguageConfig(obj.Value, _languageFontConfigs);
                            break;
                        case "languageImage":
                            LoadLanguageConfig(obj.Value, _languageImagesConfigs);
                            break;
                    }
                }
            }
        }

        private void LoadLanguageConfig(JToken token, Dictionary<string, LanguageConfig> dictionary)
        {
            if (token is not JArray jArray) return;
            foreach (var j in jArray)
            {
                var config = new LanguageConfig();
                config.Parse(j);
                dictionary[config.Key] = config;
            }
        }

        #endregion
    }
}