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

namespace XGame.Editor.Asset.Tools
{
    /// <summary>
    /// 仅限png,jpg,tga
    /// </summary>
    public class TextureSizeFixTask
    {
        //[MenuItem("Assets/TextureSizeFix", false, 132)]
        //public static void FixTextureSize()
        //{
        //    var task = new TextureSizeFixTask();
        //    task.Run();
        //}
        private HashSet<string> _texturePaths;
        private bool _haveAlpha;
        private Texture2D _source;
        private Texture2D _copy;
        private Texture2D _dest;
        public void Run()
        {
            if (!Init())
            {
                return;
            }
            var index = 0;
            foreach(var assetPath in _texturePaths)
            {
                EditorUtility.DisplayProgressBar("修复贴图尺寸...", $"Path:{assetPath}", (++index) / (float)_texturePaths.Count);
                FixTextureSize(assetPath);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
            Debug.Log($"修复贴图尺寸结束. Count:{_texturePaths.Count}");
        }
        private bool Init()
        {
            var objs = Selection.objects;
            if (objs == null || objs.Length == 0)
            {
                return false;
            }
            _texturePaths = new HashSet<string>();
            var dirPath = new List<string>();
            foreach (var obj in objs)
            {
                var assetPath = AssetDatabase.GetAssetPath(obj);
                if (FileUtil.IsTextureFile(assetPath))
                {
                    _texturePaths.Add(assetPath);
                }
                else if (Directory.Exists(assetPath))
                {
                    dirPath.Add(assetPath);
                }
            }
            if (dirPath.Count > 0)
            {
                var guids = AssetDatabase.FindAssets("t:Texture", dirPath.ToArray());
                foreach (var guid in guids)
                {
                    var assetPath = AssetDatabase.GUIDToAssetPath(guid);
                    _texturePaths.Add(assetPath);
                }
            }
            return true;
        }
        private bool FixTextureSize(string assetPath)
        {
            if (!LoadTexture(assetPath) || VerifyTextureSize())
            {
                Debug.Log($"贴图为空或者长宽符合规范。Path:{assetPath} Width:{_source?.width} Height:{_source?.height}");
                return false;
            }
            CopyTexture();
            FixTexture();
            WriteTexture(assetPath);
            Clear();
            //AssetDatabase.Refresh();
            Debug.Log($"修复贴图尺寸. Path:{assetPath}");
            return true;
        }

        private bool LoadTexture(string assetPath)
        {
            _source = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
            var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
            _haveAlpha = importer?.DoesSourceTextureHaveAlpha() ?? false;
            return _source != null && importer != null;
        }
        private bool VerifyTextureSize()
        {
            return _source.width % 4 == 0 && _source.height % 4 == 0;
        }
        private void CopyTexture()
        {
            var mat = new Material(Shader.Find("Unlit/Transparent"));
            var width = _source.width;
            var height = _source.height;
            var renderTex = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
            Graphics.Blit(_source, renderTex, mat);
            _copy = new Texture2D(width, height, _haveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, false);
            _copy.ReadPixels(new Rect(0, 0, width, height), 0, 0);
            RenderTexture.ReleaseTemporary(renderTex);
        }
        private void FixTexture()
        {
            var width = GetFourSize(_source.width);
            var height = GetFourSize(_source.height);
            _dest = new Texture2D(width, height, _haveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, false);
            for(var y = 0; y < height; y++)
            {
                for(var x = 0; x < width; x++)
                {
                    var pixel = _copy.GetPixelBilinear((x * 1.0f) / width, (y * 1.0f) / height);
                    _dest.SetPixel(x, y, pixel);
                }
            }
            _dest.Apply();
        }
        private void WriteTexture(string assetPath)
        {
            if (assetPath.EndsWith(".png", System.StringComparison.OrdinalIgnoreCase))
            {
                File.WriteAllBytes(assetPath, _dest.EncodeToPNG());
            }
            else if (assetPath.EndsWith(".jpg", System.StringComparison.OrdinalIgnoreCase))
            {
                File.WriteAllBytes(assetPath, _dest.EncodeToJPG());
            }
            else if (assetPath.EndsWith(".tga", System.StringComparison.OrdinalIgnoreCase))
            {
                File.WriteAllBytes(assetPath, _dest.EncodeToTGA());
            }
            else
            {
                Debug.LogError($"未知贴图格式，写入贴图失败: Path:{assetPath}");
            }

        }
        private void Clear()
        {
            _source = null;
            _copy = null;
            _dest = null;
        }
        private int GetFourSize(int num)
        {
            var remain = num % 4;
            if (remain == 0)
                return num;
            return num + 4 - remain;
        }
    }
}
