using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

// 创建bmfont
namespace FL.Editor
{
    public class BMFontCreator
    {
        [MenuItem("Assets/Create/XGame/CreateBMFont")]
        static void Create()
        {
            var creator = new BMFontCreator();
            creator.Start();
        }

        private void Start()
        {
            var obj = Selection.activeObject;
            string fntPath = AssetDatabase.GetAssetPath(obj);
            if (fntPath.IndexOf(".fnt") == -1)
            {
                // 不是字体文件 
                Debug.LogError("请先选择一个*.fnt!");
                return;
            } 
            //if (!File.Exists(customFontPath))
            //{
            //    Debug.LogError("The .fontsettings file not exists");
            //    return;
            //}
            Debug.Log(fntPath);

            using var reader = new StreamReader(new FileStream(fntPath, FileMode.Open));
            var charInfos = new List<CharacterInfo>();

            var reg = new Regex(@"char id=(?<id>\d+)\s+x=(?<x>\d+)\s+y=(?<y>\d+)\s+width=(?<width>\d+)\s+height=(?<height>\d+)\s+xoffset=(?<xoffset>(-|\d)+)\s+yoffset=(?<yoffset>(-|\d)+)\s+xadvance=(?<xadvance>\d+)\s+");
            string line = reader.ReadLine();
            int lineHeight = 65;
            int texWidth = 512;
            int texHeight = 512;
            var pngName = "";

            while (line != null)
            {
                if (line.IndexOf("char id=") != -1)
                {
                    var match = reg.Match(line);
                    if (match.Success)
                    {
                        var id = System.Convert.ToInt32(match.Groups["id"].Value);
                        var x = System.Convert.ToInt32(match.Groups["x"].Value);
                        var y = System.Convert.ToInt32(match.Groups["y"].Value);
                        var width = System.Convert.ToInt32(match.Groups["width"].Value);
                        var height = System.Convert.ToInt32(match.Groups["height"].Value);
                        var xoffset = System.Convert.ToInt32(match.Groups["xoffset"].Value);
                        var yoffset = System.Convert.ToInt32(match.Groups["yoffset"].Value);
                        var xadvance = System.Convert.ToInt32(match.Groups["xadvance"].Value);
                        Debug.Log($"字符:{(char)id} id:{id} width:{width} height:{height}");
                        if (height > lineHeight)
                            lineHeight = height;
                        var info = new CharacterInfo
                        {
                            index = id
                        };
                        //uv左下角(0,0)->右上角(1,1)
                        float uvx = 1f * x / texWidth;
                        float uvy = 1 - (1f * y / texHeight);
                        float uvw = 1f * width / texWidth;
                        float uvh = 1f * height / texHeight;
                        info.uvBottomLeft = new Vector2(uvx, uvy - uvh);
                        info.uvBottomRight = new Vector2(uvx + uvw, uvy - uvh);
                        info.uvTopLeft = new Vector2(uvx, uvy);
                        info.uvTopRight = new Vector2(uvx + uvw, uvy);

                        info.minX = xoffset;
                        //glyphHeight赋值时内部会加上高度，需要提前减掉高度
                        //文本上对齐时: - height，居中对其时: - height / 2
                        //下对齐时不用减
                        info.minY = yoffset - height / 2;
                        info.glyphWidth = width;
                        info.glyphHeight = height;
                        info.advance = xadvance;
                        //info.size = 18;
                        //info.style = FontStyle.Italic;
                        charInfos.Add(info);
                    }
                }
                else if (line.IndexOf("scaleW=") != -1)
                {
                    var reg2 = new Regex(@"common lineHeight=(?<lineHeight>\d+)\s+.*scaleW=(?<scaleW>\d+)\s+scaleH=(?<scaleH>\d+)");
                    var match = reg2.Match(line);
                    if (match.Success)
                    {
                        lineHeight = System.Convert.ToInt32(match.Groups["lineHeight"].Value);
                        texWidth = System.Convert.ToInt32(match.Groups["scaleW"].Value);
                        texHeight = System.Convert.ToInt32(match.Groups["scaleH"].Value);
                    }
                }
                else if (line.IndexOf("file=") != -1)
                {
                    var match = Regex.Match(line, @"\s+.*file=""(.+?)""");
                    if (match.Success)
                    {
                        pngName = match.Groups[1].Value;
                    }
                }
                line = reader.ReadLine();
            }
            Debug.Log($"字体贴图 Name:{pngName} Width:{texWidth} Height:{texHeight} ");
            if (string.IsNullOrEmpty(pngName))
            {
                Debug.LogError($"字体贴图名字为空, 请检查*.fnt文件.");
                return;
            }
            var texturePath = Path.Combine(Path.GetDirectoryName(fntPath), pngName);
            var texture = AssetDatabase.LoadAssetAtPath<Texture>(texturePath);
            if (texture == null)
            {
                Debug.LogError($"找不到字体贴图. Path:{texturePath}");
                return;
            }
            var customFontPath = fntPath.Replace(".fnt", ".fontsettings");
            var customFont = AssetDatabase.LoadAssetAtPath<Font>(customFontPath);
            if (customFont == null)
            {
                customFont = new Font(Path.GetFileNameWithoutExtension(fntPath));
                AssetDatabase.CreateAsset(customFont, customFontPath);
            }
            var matiralPath = fntPath.Replace(".fnt", ".mat");
            var material = AssetDatabase.LoadAssetAtPath<Material>(matiralPath);
            if (material == null)
            {
                material = new Material(Shader.Find("XGame/Text Shader"));
                AssetDatabase.CreateAsset(material, matiralPath);
            }
            material.mainTexture = texture;
            customFont.material = material;
            customFont.characterInfo = charInfos.ToArray();
            EditorUtility.SetDirty(material);
            EditorUtility.SetDirty(customFont);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            if (customFont.lineHeight < lineHeight)
            {
                Debug.LogWarning($"需要手动修改字体的LineSpacing. 当前:{customFont.lineHeight} 推荐:{lineHeight}");
            }
            Debug.Log($"字体生成完成. Path:{customFontPath}");
        }
    }
}
