using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.VFX;

namespace UNSLOW.EffectPractice
{
    /// <summary>同じしきい値で、本体の消失と境界からの粒子発生を進める。</summary>
    public sealed class MeshDissolveDemo : MonoBehaviour
    {
        [SerializeField] private Renderer[] meshRenderers = System.Array.Empty<Renderer>();
        [SerializeField] private VisualEffect[] effects = System.Array.Empty<VisualEffect>();
        [SerializeField, Min(0)] private float holdDuration = 1;
        [SerializeField, Min(0.1f)] private float dissolveDuration = 3;
        [SerializeField, Min(0)] private float residueDuration = 2;
        [SerializeField, Min(0)] private float candidateRate = 60000;

        private static readonly int ThresholdId = Shader.PropertyToID("_Threshold");
        private MaterialPropertyBlock properties;
        private float elapsed;
        public float Elapsed => elapsed;
        public float Progress => Mathf.Clamp01((elapsed - holdDuration) / dissolveDuration);

        private void Awake() => properties = new MaterialPropertyBlock();
        private void Start() => Replay();

        private void Update()
        {
            elapsed += Time.deltaTime;
            if (elapsed >= holdDuration + dissolveDuration + residueDuration ||
                Keyboard.current?.spaceKey.wasPressedThisFrame == true)
                Replay();
            ApplyProgress();
        }

        public void Replay()
        {
            elapsed = 0;
            ApplyProgress();
            foreach (var effect in effects)
            {
                if (effect == null) continue;
                effect.startSeed = 14;
                effect.resetSeedOnPlay = false;
                effect.Reinit();
            }
        }

        private void ApplyProgress()
        {
            // ShaderとGraphは同じ範囲のマスクを使う。前後に余裕を設けて完全に表示・消失させる。
            float threshold = Mathf.Lerp(-0.2f, 1.2f, Progress);
            foreach (var meshRenderer in meshRenderers)
            {
                if (meshRenderer == null) continue;
                meshRenderer.GetPropertyBlock(properties);
                properties.SetFloat(ThresholdId, threshold);
                meshRenderer.SetPropertyBlock(properties);
            }
            foreach (var effect in effects)
            {
                if (effect == null) continue;
                effect.SetFloat("DissolveThreshold", threshold);
                effect.SetFloat("CandidateRate", elapsed >= holdDuration && Progress < 1 ? candidateRate : 0);
            }
        }
    }
}
