using UnityEditor;
using UnityEngine;

namespace CatsUdonTools.Editor
{
    /// <summary>
    /// 入稿フォルダへコピーしたテクスチャに Crunch 圧縮をかける。
    /// エディタ時のみ動作し、プレイヤービルドには含まれない。コピー側の Importer だけを変更する
    /// </summary>
    internal static class SubmissionTextureCompression
    {
        private const string StandalonePlatformName = "Standalone";
        private const int CrunchCompressionQuality = 100;

        /// <summary>
        /// texturesFolder 配下の全テクスチャに Crunch 圧縮を設定して再インポートする
        /// </summary>
        public static void ApplyCrunch(string texturesFolder)
        {
            var textureGuids = AssetDatabase.FindAssets("t:Texture", new[] { texturesFolder });

            foreach (var textureGuid in textureGuids)
            {
                ApplyCrunchToTexture(AssetDatabase.GUIDToAssetPath(textureGuid));
            }
        }

        private static void ApplyCrunchToTexture(string texturePath)
        {
            if (AssetImporter.GetAtPath(texturePath) is not TextureImporter importer)
            {
                return;
            }

            if (importer.GetPlatformTextureSettings(StandalonePlatformName).overridden)
            {
                importer.ClearPlatformTextureSettings(StandalonePlatformName);
            }

            // 明示フォーマットのままだと圧縮・Crunch 設定が無視されるため Automatic に戻す
            importer.textureFormat = TextureImporterFormat.Automatic;
            importer.textureCompression = TextureImporterCompression.Compressed;
            importer.crunchedCompression = true;
            importer.compressionQuality = CrunchCompressionQuality;

            if (ShouldRoundToNearestPowerOfTwo(importer))
            {
                importer.npotScale = TextureImporterNPOTScale.ToNearest;
            }

            importer.SaveAndReimport();
        }

        // Crunch は 4 の倍数でないサイズでは効かず、Unity が黙って非圧縮に落とすため 2 のべき乗へ寄せる。
        // Sprite は ToNearest にするとサブアセット参照が切れるため触らない
        private static bool ShouldRoundToNearestPowerOfTwo(TextureImporter importer)
        {
            if (importer.textureShape != TextureImporterShape.Texture2D)
            {
                return false;
            }

            if (importer.textureType == TextureImporterType.Sprite)
            {
                return false;
            }

            if (importer.npotScale != TextureImporterNPOTScale.None)
            {
                return false;
            }

            importer.GetSourceTextureWidthAndHeight(out var width, out var height);
            return !Mathf.IsPowerOfTwo(width) || !Mathf.IsPowerOfTwo(height);
        }
    }
}
