﻿using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using JLGames.RocketDriver.CSharp.Extensions;
using JLGames.RocketDriver.Actions.Utils;
using JLGames.RocketDriver.CSharp.Event;

namespace JLGames.RocketDriver.Actions.i18n
{
    public class I18NManager : EventDispatcher, II18NManager
    {
        private readonly I18NRegister m_Register = new I18NRegister();

        // 
        private readonly Dictionary<string, Dictionary<string, string>> m_Map = new Dictionary<string, Dictionary<string, string>>();

        public I18NRegister Register => m_Register;

        public void ClearData()
        {
            m_Map.Clear();
        }

        public void LoadData()
        {
            var loader = m_Register.Loader;
            if (null == loader) return;
            var extension = m_Register.FileExtension;
            m_Register.ForeachRegister(ele =>
            {
                var assetPath = GetFilePath(ele.FileBasePath, ele.LangSuffix, extension);
                loader.LoadFile(ele.FileBundle, assetPath, (textAsset, succ) =>
                {
                    if (!succ) return;
                    AppendData(ele.FileKey, ele.LangName, textAsset.text, m_Register.DataParser);
                    DispatchEvent(I18NEvents.EventDataElementLoaded, ele);
                });
            });
            DispatchEvent(I18NEvents.EventDataLoaded, null);
        }

        public void LoadDataFromSettings(I18NSettings settings)
        {
            if (null == settings) return;
            var infos = settings.GetAssetInfos();
//            DebugUtil.Log("Info.Len =", infos?.Length);
            if (null == infos || infos.Length == 0) return;
            foreach (var info in infos)
            {
                m_Register.RegisterLang(info.LangName, info.Default);
                m_Register.RegisterFileInfo(info.FileKey, info.Default);
                AppendData(info.FileKey, info.LangName, info.Content, settings.DataParser);
                DispatchEvent(I18NEvents.EventSettingElementLoaded, info);
            }

            DispatchEvent(I18NEvents.EventDataLoaded, null);
//            PrintInfos();
        }

        public void AppendData(string fileKey, string langName, string data)
        {
            AppendData(fileKey, langName, data, m_Register.DataParser);
        }

        private void AppendData(string fileKey, string langName, string data, II18NDataParser parser)
        {
            var map = parser?.ParserData(data);
            if (map == null)
            {
                DebugUtil.LogWarning($"ParseData(FileKey={fileKey}, LangName={langName}) Fail.");
                return;
            }

            var key = GetMapKey(fileKey, langName);
            m_Map[key] = map;
        }

        public bool Contains(string fileKey, string langName)
        {
            var key = GetMapKey(fileKey, langName);
            return m_Map.ContainsKey(key);
        }

        public string GetValue(string id)
        {
            return GetValue(id, m_Register.DefaultFileKey, m_Register.DefaultLang);
        }

        public string GetValue(string id, string fileKey)
        {
            return GetValue(id, fileKey, m_Register.DefaultLang);
        }

        public string GetValue(string id, string fileKey, string langName)
        {
            var key = GetMapKey(fileKey, langName);
            if (!m_Map.ContainsKey(key)) return null;
            var valueMap = m_Map[key];
            if (!valueMap.ContainsKey(id)) return null;
            return valueMap[id];
        }

        public string GetContent(string content)
        {
            return GetContent(content, m_Register.DefaultFileKey, m_Register.DefaultLang);
        }

        public string GetContent(string content, string fileKey)
        {
            return GetContent(content, fileKey, m_Register.DefaultLang);
        }

        /// <summary>
        /// 格式: {{id}}
        /// +? : 前一个字符1次或无限次扩展，最小匹配
        /// </summary>
        private static readonly Regex m_RegValue = new Regex(@"{{.+?}}");

        private static readonly StringBuilder m_ContentBuilder = new StringBuilder();

        public string GetContent(string content, string fileKey, string langName)
        {
            var arr = content.Split(m_RegValue, true, matched => GetValueByMatched(matched, fileKey, langName));
            if (null == arr || arr.Length == 0) return null;
            m_ContentBuilder.Clear();
            for (var index = 0; index < arr.Length; index++)
            {
                m_ContentBuilder.Append(arr[index]);
            }

            return m_ContentBuilder.ToString();
        }

        private string GetValueByMatched(string matched, string fileKey, string langName)
        {
            var id = matched.Substring(2, matched.Length - 4).Trim();
            var value = GetValue(id, fileKey, langName);
            return value ?? matched;
        }

        private string GetMapKey(string fileKey, string langeName)
        {
            return $"{fileKey}_{langeName}";
        }

        private string GetFilePath(string fileBasePath, string langSuffix, string fileExtension)
        {
            return string.IsNullOrEmpty(langSuffix) ? $"{fileBasePath}.{fileExtension}" : $"{fileBasePath}_{langSuffix}.{fileExtension}";
        }

        public void PrintInfos()
        {
#if UNITY_EDITOR
            var sb = new StringBuilder("I18NManager.Data:\n");
            foreach (var pair in m_Map)
            {
                sb.Append($"  MapKey={pair.Key}\n");
                foreach (var kv in pair.Value)
                {
                    sb.Append($"    \"{kv.Key}\"=\"{kv.Value}\"\n");
                }
            }

            DebugUtil.Log(sb.ToString());
#endif
        }
    }
}