using JetBrains.Annotations;
using UnityEngine;

namespace Obvious.Soap.Example
{
    public class Health : MonoBehaviour
    {
        [SerializeField] private FloatVariable _currentHealth = null;
        [SerializeField] private FloatReference _maxHealth = null;

        [Header("Events")] [SerializeField] private ScriptableEventInt _onPlayerDamaged = null;
        [SerializeField] private ScriptableEventInt _onPlayerHealed = null;
        [SerializeField] private ScriptableEventNoParam _onPlayerDeath = null;

        private bool IsDead => _currentHealth <= 0f;

        private void Start()
        {
            _currentHealth.Value = _maxHealth.Value;
            _currentHealth.OnValueChanged += OnHealthChanged;
        }

        private void OnDestroy()
        {
            _currentHealth.OnValueChanged -= OnHealthChanged;
        }

        private void OnHealthChanged(float newValue)
        {
            var diff = newValue - _currentHealth.PreviousValue;
            if (diff < 0)
            {
                OnDamaged(Mathf.Abs(diff));
            }
            else
            {
                OnHealed(diff);
            }
        }

        private void OnDamaged(float value)
        {
            if (IsDead)
                OnDeath();
            else
                _onPlayerDamaged.Raise(Mathf.RoundToInt(value));
        }

        private void OnHealed(float value)
        {
            _onPlayerHealed.Raise(Mathf.RoundToInt(value));
        }

        private void OnDeath()
        {
            _onPlayerDeath.Raise();
        }

        //if you don't want to modify directly the health, you can also do it like this
        //Used in the Event example.
        [UsedImplicitly]
        public void TakeDamage(int amount)
        {
            _currentHealth.Add(-amount);
        }
    }
}