﻿using System.Collections.Generic;
using JLGames.RocketDriver.Actions.Utils;
using UnityEngine;

namespace JLGames.RocketDriver.Actions.i18n
{
    public sealed class I18NRegister
    {
        private string m_FileType = I18NDataFiles.JSON;
        private II18NLoaderAdapter m_Loader = new I18NtLoader();
        private II18NDataParser m_DataParser = new FlatJsonParser();

        private readonly List<string> m_LangNames = new List<string>();
        private readonly List<string> m_FileKeys = new List<string>();
        private string m_DefaultLang;
        private string m_DefaultFileKey;

        private readonly Dictionary<string, RegisterFileLoadingInfo> m_FilePathMap = new Dictionary<string, RegisterFileLoadingInfo>();
        private readonly Dictionary<string, string> m_LangSuffixMap = new Dictionary<string, string>();
        private readonly Dictionary<SystemLanguage, string> m_I18NCodeMap = new Dictionary<SystemLanguage, string>();

        public string FileType => m_FileType;
        public string FileExtension => I18NDataFiles.GetFileExtension(m_FileType);
        public II18NLoaderAdapter Loader => m_Loader;
        public II18NDataParser DataParser => m_DataParser;
        public string[] LangNames => m_LangNames.ToArray();
        public string[] FileKeys => m_FileKeys.ToArray();
        public string DefaultLang => m_DefaultLang;
        public string DefaultFileKey => m_DefaultFileKey;

        public void SetDataFileType(string fileType)
        {
            if (fileType == m_FileType) return;
            m_FileType = fileType;
            m_DataParser = DataParserFactory.GenDataParser(fileType);
        }

        /// <summary>
        /// Set the default language (requires that the language has been registered, otherwise return false)
        /// 设置默认语言(要求语言已经注册完成，否则返回false)
        /// </summary>
        /// <param name="lang"></param>
        /// <returns></returns>
        public bool SetDefaultLang(string lang)
        {
            if (!m_LangNames.Contains(lang)) return false;
            m_DefaultLang = lang;
            return true;
        }

        /// <summary>
        /// Set the default file (requires that the file set has been registered, otherwise returns false)
        /// 设置默认文件(要求文件集已经注册完成，否则返回false)
        /// </summary>
        /// <param name="fileKey"></param>
        /// <returns></returns>
        public bool SetDefaultFileKey(string fileKey)
        {
            if (!m_FileKeys.Contains(fileKey)) return false;
            m_DefaultFileKey = fileKey;
            return true;
        }

        /// <summary>
        /// Set data loader.
        /// 设置数据加载器
        /// </summary>
        /// <param name="loader"></param>
        public void SetLoader(II18NLoaderAdapter loader)
        {
            m_Loader = loader;
        }

        /// <summary>
        /// Set data parser
        /// 设置数据解释器
        /// </summary>
        /// <param name="parser"></param>
        public void SetDataParser(II18NDataParser parser)
        {
            m_DataParser = parser;
        }

        /// <summary>
        /// Set language CodeMap
        /// 设置语言编码映射
        /// </summary>
        /// <param name="codeMap"></param>
        public void SetLangCodeMap(Dictionary<SystemLanguage, string> codeMap)
        {
            m_I18NCodeMap.Clear();
            if (null == codeMap || codeMap.Count == 0) return;
            foreach (var pair in codeMap)
            {
                m_I18NCodeMap.Add(pair.Key, pair.Value);
            }
        }

        /// <summary>
        /// Register language
        /// 注册语言
        /// Language file suffix with language name
        /// 语言文件后缀使用语言名称
        /// Not set as default
        /// 不设置为默认
        /// </summary>
        /// <param name="langName">Language name 语言名称</param>
        /// <param name="default">Set as default? 是否设置为默认</param>
        public void RegisterLang(string langName, bool @default = false)
        {
            RegisterLang(langName, langName, @default);
        }

        /// <summary>
        /// Register language
        /// 注册语言
        /// </summary>
        /// <param name="langName">Language name 语言名称</param>
        /// <param name="langSuffix">Language file suffix 语言文件后缀</param>
        /// <param name="default">Set as default? 是否设置为默认</param>
        public void RegisterLang(string langName, string langSuffix, bool @default = false)
        {
            m_LangSuffixMap[langName] = langSuffix;
            if (!m_LangNames.Contains(langName)) m_LangNames.Add(langName);
            if (@default) m_DefaultLang = langName;
        }

        /// <summary>
        /// Check if a language is already registered
        /// 判断语言是否已经注册
        /// </summary>
        /// <param name="langName"></param>
        /// <returns></returns>
        public bool ContainsLang(string langName)
        {
            return m_LangNames.Contains(langName);
        }

        /// <summary>
        /// Register the file set info.
        /// 注册文件集信息
        /// </summary>
        /// <param name="fileKey">file set key name 文件映射Key</param>
        /// <param name="default"></param>
        public void RegisterFileInfo(string fileKey, bool @default = false)
        {
            if (!m_FileKeys.Contains(fileKey)) m_FileKeys.Add(fileKey);
            if (@default) m_DefaultFileKey = fileKey;
        }

        /// <summary>
        /// Register loading info of the file set.
        /// 注册文件集加载信息
        /// </summary>
        /// <param name="fileKey">file set key name 文件映射Key</param>
        /// <param name="fileBundle">bundle of the file set 文件集所在bundle</param>
        /// <param name="filePath"></param>
        /// <param name="default"></param>
        public void RegisterFileLoadingInfo(string fileKey, string fileBundle, string filePath, bool @default = false)
        {
            m_FilePathMap[fileKey] = new RegisterFileLoadingInfo(fileKey, fileBundle, filePath);
            if (!m_FileKeys.Contains(fileKey)) m_FileKeys.Add(fileKey);
            if (@default) m_DefaultFileKey = fileKey;
        }

        /// <summary>
        /// Whether to include data files
        /// 是否包含数据文件
        /// </summary>
        /// <param name="fileKey"></param>
        /// <returns></returns>
        public bool ContainsFile(string fileKey)
        {
            return m_FileKeys.Contains(fileKey);
        }

        /// <summary>
        /// Reset register
        /// 清空注册表
        /// </summary>
        public void ResetRegister()
        {
            m_LangSuffixMap.Clear();
            m_FilePathMap.Clear();
            m_I18NCodeMap.Clear();

            m_LangNames.Clear();
            m_FileKeys.Clear();

            m_DefaultLang = null;
            m_DefaultFileKey = null;
        }

        /// <summary>
        /// Get i18n language code through SystemLanguage
        /// 通过SystemLanguage取国际化语言代码
        /// </summary>
        /// <param name="sysLang"></param>
        /// <returns></returns>
        public string GetLanguageCode(SystemLanguage sysLang)
        {
            if (m_I18NCodeMap.Count == 0) return I18NUtils.GetLanguageCode(sysLang);
            if (m_I18NCodeMap.ContainsKey(sysLang)) return m_I18NCodeMap[sysLang];
            if (m_I18NCodeMap.ContainsKey(SystemLanguage.Unknown)) return m_I18NCodeMap[SystemLanguage.Unknown];
            return I18NUtils.GetLanguageCode(sysLang);
        }

        public void ForeachRegister(I18NDelegate.EachRegister eachFunc)
        {
            if (null == eachFunc) return;
            foreach (var filePair in m_FilePathMap)
            {
                foreach (var langPair in m_LangSuffixMap)
                {
                    var ele = new I18NRegisterElement
                    {
                        m_LangName = langPair.Key,
                        m_LangSuffix = langPair.Value,
                        m_FileKey = filePair.Value.FileKey,
                        m_FileBundle = filePair.Value.FileBundle,
                        m_FileBasePath = filePair.Value.FilePath,
                    };
                    eachFunc.Invoke(ele);
                }
            }
        }
    }
}