using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Byway.Thrift.Data;
using Thrift.Protocol;
using Thrift.Transport.Client;
using UnityEditor;
using UnityEngine;

namespace FontTools
{
    /// <summary>
    /// 语言字符集生成器
    /// 从 AllConfigs 读取 LanguageData 表，提取三种语言的字符集并保存为txt
    /// </summary>
    public class LanguageCharsetGenerator : EditorWindow
    {
        private const string DEFAULT_OUTPUT_PATH = "Assets/Design_SubModule/Scripts/Editor/ThriftPipelineTool/CharacterSets";
        
        private string outputPath = DEFAULT_OUTPUT_PATH;
        private TextAsset allConfigsFile;
        private Vector2 scrollPosition;
        private string statusLog = "";
        private bool isProcessing = false;
        
        private Dictionary<string, int> charCounts = new Dictionary<string, int>();
        
        [MenuItem("配置表pipeline/字体/生成字符集")]
        public static void ShowWindow()
        {
            var window = GetWindow<LanguageCharsetGenerator>("字符集生成器");
            window.minSize = new Vector2(600, 500);
            window.Show();
        }
        
        private void OnEnable()
        {
            // 自动查找 AllConfigs.bytes
            AutoFindAllConfigs();
        }
        
        private void OnGUI()
        {
            EditorGUILayout.Space(10);
            EditorGUILayout.LabelField("语言字符集生成器", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox(
                "从 AllConfigs.bytes 读取 LanguageData 表\n" +
                "提取 En_US、Zh_CN、Pt_BR 三个语言列的所有字符（去重）\n" +
                "生成三个字符集txt文件",
                MessageType.Info
            );
            
            EditorGUILayout.Space(10);
            
            // AllConfigs 文件选择
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.LabelField("1. 选择 AllConfigs.bytes 文件:", EditorStyles.boldLabel);
            EditorGUILayout.BeginHorizontal();
            allConfigsFile = EditorGUILayout.ObjectField("AllConfigs:", allConfigsFile, typeof(TextAsset), false) as TextAsset;
            if (GUILayout.Button("自动查找", GUILayout.Width(80)))
            {
                AutoFindAllConfigs();
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
            
            EditorGUILayout.Space(5);
            
            // 输出路径选择
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.LabelField("2. 选择输出目录:", EditorStyles.boldLabel);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.TextField(outputPath);
            if (GUILayout.Button("浏览", GUILayout.Width(60)))
            {
                string selected = EditorUtility.OpenFolderPanel("选择输出目录", outputPath, "");
                if (!string.IsNullOrEmpty(selected))
                {
                    // 转换为相对路径
                    if (selected.StartsWith(Application.dataPath))
                    {
                        outputPath = "Assets" + selected.Substring(Application.dataPath.Length);
                    }
                    else
                    {
                        outputPath = selected;
                    }
                }
            }
            if (GUILayout.Button("重置", GUILayout.Width(60)))
            {
                outputPath = DEFAULT_OUTPUT_PATH;
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
            
            EditorGUILayout.Space(10);
            
            // 生成按钮
            GUI.enabled = !isProcessing && allConfigsFile != null;
            if (GUILayout.Button("生成字符集", GUILayout.Height(40)))
            {
                GenerateCharsets();
            }
            GUI.enabled = true;
            
            EditorGUILayout.Space(10);
            
            // 统计信息
            if (charCounts.Count > 0)
            {
                EditorGUILayout.BeginVertical("box");
                EditorGUILayout.LabelField("字符统计:", EditorStyles.boldLabel);
                foreach (var kvp in charCounts.OrderBy(x => x.Key))
                {
                    EditorGUILayout.LabelField($"  {kvp.Key}: {kvp.Value} 个字符");
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.Space(5);
            }
            
            // 日志区域
            EditorGUILayout.LabelField("执行日志:", EditorStyles.boldLabel);
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, "box", GUILayout.Height(200));
            EditorGUILayout.TextArea(statusLog, EditorStyles.wordWrappedLabel);
            EditorGUILayout.EndScrollView();
        }
        
        /// <summary>
        /// 自动查找 AllConfigs.bytes
        /// </summary>
        private void AutoFindAllConfigs()
        {
            string[] guids = AssetDatabase.FindAssets("AllConfigs t:TextAsset");
            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                if (path.EndsWith(".bytes", StringComparison.OrdinalIgnoreCase))
                {
                    allConfigsFile = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
                    if (allConfigsFile != null)
                    {
                        Log($"✓ 自动找到 AllConfigs: {path}");
                        return;
                    }
                }
            }
            Log("⚠ 未找到 AllConfigs.bytes，请手动选择");
        }
        
        /// <summary>
        /// 生成字符集
        /// </summary>
        private void GenerateCharsets()
        {
            isProcessing = true;
            statusLog = "";
            charCounts.Clear();
            
            try
            {
                Log("========================================");
                Log("开始生成字符集");
                Log("========================================\n");
                
                // 步骤1: 反序列化 AllConfigs
                Log("[步骤1] 读取 AllConfigs.bytes...");
                var allConfigs = DeserializeAllConfigs(allConfigsFile.bytes);
                if (allConfigs == null)
                {
                    LogError("✗ 反序列化 AllConfigs 失败！");
                    return;
                }
                Log("✓ AllConfigs 读取成功\n");
                
                // 步骤2: 获取 LanguageData
                Log("[步骤2] 提取 LanguageData...");
                var languageData = allConfigs.LanguageData;
                if (languageData == null || languageData.Languagedatas == null)
                {
                    LogError("✗ LanguageData 不存在或为空！");
                    return;
                }
                Log($"✓ 找到 {languageData.Languagedatas.Count} 条语言数据\n");
                
                // 步骤3: 提取字符集
                Log("[步骤3] 提取字符集...");
                var charsets = ExtractCharsets(languageData);
                
                // 步骤4: 保存txt文件
                Log("\n[步骤4] 保存txt文件...");
                SaveCharsets(charsets);
                
                Log("\n========================================");
                Log("✓ 字符集生成完成！");
                Log($"输出目录: {outputPath}");
                Log("========================================");
                
                EditorUtility.DisplayDialog("完成", 
                    $"字符集生成成功！\n\n" +
                    $"En_US: {charCounts["En_US"]} 个字符\n" +
                    $"Zh_CN: {charCounts["Zh_CN"]} 个字符\n" +
                    $"Pt_BR: {charCounts["Pt_BR"]} 个字符\n\n" +
                    $"文件保存在: {outputPath}", 
                    "确定");
            }
            catch (Exception ex)
            {
                LogError($"✗ 生成失败: {ex.Message}\n{ex.StackTrace}");
                EditorUtility.DisplayDialog("错误", $"生成失败:\n{ex.Message}", "确定");
            }
            finally
            {
                isProcessing = false;
                Repaint();
            }
        }
        
        /// <summary>
        /// 反序列化 AllConfigs
        /// </summary>
        private AllConfigs DeserializeAllConfigs(byte[] bytes)
        {
            try
            {
                using (var transport = new TMemoryBufferTransport(bytes, new Thrift.TConfiguration()))
                using (var protocol = new TBinaryProtocol(transport))
                {
                    var allConfigs = new AllConfigs();
                    allConfigs.ReadAsync(protocol, System.Threading.CancellationToken.None).Wait();
                    return allConfigs;
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"反序列化失败: {ex.Message}");
                return null;
            }
        }
        
        /// <summary>
        /// 从 LanguageData 提取字符集
        /// </summary>
        private Dictionary<string, HashSet<char>> ExtractCharsets(LanguageData languageData)
        {
            var charsets = new Dictionary<string, HashSet<char>>
            {
                { "En_US", new HashSet<char>() },
                { "Zh_CN", new HashSet<char>() },
                { "Pt_BR", new HashSet<char>() }
            };
            
            int processedCount = 0;
            int totalCount = languageData.Languagedatas.Count;
            
            // 遍历所有行
            foreach (var kvp in languageData.Languagedatas)
            {
                var item = kvp.Value;
                
                // 提取每个语言列的字符
                AddChars(charsets["En_US"], item.En_US);
                AddChars(charsets["Zh_CN"], item.Zh_CN);
                AddChars(charsets["Pt_BR"], item.Pt_BR);
                
                processedCount++;
                if (processedCount % 100 == 0)
                {
                    Log($"  处理进度: {processedCount}/{totalCount}");
                }
            }
            
            // 确保所有字符集都包含下划线和省略号
            foreach (var charset in charsets.Values)
            {
                charset.Add('_');  // 下划线
                charset.Add('…');  // 省略号
            }
            
            // 英文字符集额外添加美元符号
            charsets["En_US"].Add('$');
            
            // 统计
            charCounts["En_US"] = charsets["En_US"].Count;
            charCounts["Zh_CN"] = charsets["Zh_CN"].Count;
            charCounts["Pt_BR"] = charsets["Pt_BR"].Count;
            
            Log($"✓ En_US: {charCounts["En_US"]} 个字符");
            Log($"✓ Zh_CN: {charCounts["Zh_CN"]} 个字符");
            Log($"✓ Pt_BR: {charCounts["Pt_BR"]} 个字符");
            
            return charsets;
        }
        
        /// <summary>
        /// 添加字符到集合（排除控制字符）
        /// </summary>
        private void AddChars(HashSet<char> charset, string text)
        {
            if (string.IsNullOrEmpty(text))
                return;
            
            foreach (char c in text)
            {
                if (!char.IsControl(c)) // 排除换行符、制表符等控制字符
                {
                    charset.Add(c);
                }
            }
        }
        
        /// <summary>
        /// 保存字符集到txt文件
        /// </summary>
        private void SaveCharsets(Dictionary<string, HashSet<char>> charsets)
        {
            // 创建输出目录
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
                Log($"✓ 创建目录: {outputPath}");
            }
            
            foreach (var kvp in charsets)
            {
                string langName = kvp.Key;
                var chars = kvp.Value;
                
                // 按 Unicode 排序
                var sortedChars = chars.OrderBy(c => (int)c).ToArray();
                string content = new string(sortedChars);
                
                // 保存文件
                string filePath = Path.Combine(outputPath, $"{langName}_charset.txt");
                File.WriteAllText(filePath, content, System.Text.Encoding.UTF8);
                
                Log($"✓ {langName}: {filePath} ({chars.Count} 字符)");
            }
            
            // 刷新 AssetDatabase
            AssetDatabase.Refresh();
        }
        
        private void Log(string message)
        {
            statusLog += message + "\n";
            Repaint();
        }
        
        private void LogError(string message)
        {
            statusLog += $"<color=red>{message}</color>\n";
            Debug.LogError(message);
            Repaint();
        }
    }
}
