using UnityEngine;

namespace UNSLOW.EffectPractice.FirstTerm.DamageNumbers
{
    [RequireComponent(typeof(RectTransform))]
    public class UIAnimator : MonoBehaviour
    {
        [Tooltip("再生に使うプリセットです 設定すると Play Mode 中にカーブを編集してもアセット側に保存できます")]
        [SerializeField] private UIAnimationPreset preset;

        [SerializeField] private UIAnimationSettings localSettings = new();

        [Tooltip("この GameObject が有効になった時に自動でアニメーションを開始します")]
        [SerializeField] private bool playOnEnable = true;

        [Tooltip("アニメーション完了時にこの GameObject を削除します ループ再生が有効な場合は無視されます")]
        [SerializeField] private bool destroyOnComplete;

        private RectTransform _rectTransform;
        private CanvasGroup _canvasGroup;
        private Vector2 _startAnchoredPosition;
        private Vector3 _startScale;
        private float _startAlpha;
        private float _elapsedTime;
        private bool _isPlaying;

        public float LifeTime
        {
            get => ActiveSettings.LifeTime;
        }

        private UIAnimationSettings ActiveSettings => preset != null ? preset.Settings : localSettings;

        private void Awake()
        {
            _rectTransform = GetComponent<RectTransform>();
            _canvasGroup = GetComponent<CanvasGroup>();

            if (_canvasGroup == null)
                _canvasGroup = gameObject.AddComponent<CanvasGroup>();
        }

        private void OnEnable()
        {
            if (playOnEnable)
                Play();
        }

        private void Update()
        {
            if (!_isPlaying)
                return;

            _elapsedTime += Time.deltaTime;
            var activeLifeTime = ActiveSettings.LifeTime;
            var normalizedTime = activeLifeTime <= 0f ? 1f : Mathf.Clamp01(_elapsedTime / activeLifeTime);

            Apply(normalizedTime);

            if (normalizedTime < 1f)
                return;
            
            if (ActiveSettings.Loop && activeLifeTime > 0f)
            {
                _elapsedTime %= activeLifeTime;
                return;
            }

            _isPlaying = false;

            if (destroyOnComplete)
                Destroy(gameObject);
        }

        /// <summary>
        ///     再生
        /// </summary>
        public void Play()
        {
            _elapsedTime = 0f;
            _isPlaying = true;
            _startAnchoredPosition = _rectTransform.anchoredPosition;
            _startScale = _rectTransform.localScale;
            _startAlpha = _canvasGroup.alpha;
            Apply(0f);
        }

        /// <summary>
        ///     停止
        /// </summary>
        public void Stop()
        {
            _isPlaying = false;
        }

        /// <summary>
        ///     正規化された時間での再生
        /// </summary>
        /// <param name="normalizedTime"></param>
        private void Apply(float normalizedTime)
        {
            var settings = ActiveSettings;
            var positionX = settings.PositionXCurve.Evaluate(normalizedTime);
            var positionY = settings.UseSharedPositionCurve ? positionX : settings.PositionYCurve.Evaluate(normalizedTime);

            var scaleX = settings.ScaleXCurve.Evaluate(normalizedTime);
            var scaleY = settings.UseSharedScaleCurve ? scaleX : settings.ScaleYCurve.Evaluate(normalizedTime);
            var alpha = settings.AlphaCurve.Evaluate(normalizedTime);

            _rectTransform.localScale = new Vector3(_startScale.x * scaleX, _startScale.y * scaleY, _startScale.z);
            _rectTransform.anchoredPosition = _startAnchoredPosition + new Vector2(positionX, positionY);
            _canvasGroup.alpha = _startAlpha * alpha;
        }
    }
}
