using Cinemachine;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

[Serializable]
public struct AnimationState
{ 
    public float MinLife;
    public Sprite Sprite;
}

[SelectionBase]
public class Building : MonoBehaviour
{
    [SerializeField] private SpriteRenderer _spriteRenderer;
    [SerializeField] private float _life = 0.0f;
    [SerializeField] private List<AnimationState> _animationStates = new List<AnimationState>();
    private List<Monster> _attackers = new List<Monster>();

    private int _currentAnimation = 0;
    private BuildingManager _buildingManager;

    [SerializeField] private UnityEvent _onStateLost = null;
    public int AttackerCount { get { return _attackers.Count; } }
    public bool IsAlive { get { return _life>0.0f; } }
    public float Life { get { return _life; } }

    [Header("Noise")]
    [SerializeField] private float _durationNoise = 0.1f;
    [SerializeField] private float _amplitudeOnKill = 0.1f;
    [SerializeField] private float _frequenceOnKill = 1.0f;

    #region Events
    private event Action<Building> _onBreakedEvent = null;
    public event Action<Building> OnBreaked
    {
        add
        {
            _onBreakedEvent -= value;
            _onBreakedEvent += value;
        }
        remove
        {
            _onBreakedEvent -= value;
        }
    }

    /// <summary>
    /// Return life lost and life remaining.
    /// </summary>
    private event Action<float, float> _onLifeLostEvent = null;

    /// <summary>
    /// <inheritdoc cref="_onLifeLostEvent"/>
    /// </summary>
    public event Action<float, float> OnLifeLost
    {
        add
        {
            _onLifeLostEvent -= value;
            _onLifeLostEvent += value;
        }
        remove
        {
            _onLifeLostEvent -= value;
        }
    }
    #endregion Events

    public void Init(BuildingManager buildingManager)
    {
        _buildingManager = buildingManager;
        _spriteRenderer.sprite = _animationStates[_currentAnimation].Sprite;
    }

    public void Attacked(Monster attacker)
    {
        if (_attackers.Contains(attacker) == false)
        {
            _attackers.Add(attacker);
        }
    }

    public void Damage(float damage)
    {
        _life -= damage;
        _onLifeLostEvent?.Invoke(damage, _life);
        if (_life < 0.0f)
        {
            _spriteRenderer.sprite = _animationStates[_animationStates.Count-1].Sprite;
            NoiseManager.Instance.PlayNoise(_amplitudeOnKill, _frequenceOnKill, _durationNoise);
            foreach (Monster attacker in _attackers)
            {
                attacker.OnBuildingKilled();
            }
            _onBreakedEvent?.Invoke(this);
            _attackers.Clear();
        }
        else
        {
            while (_currentAnimation < _animationStates.Count && _animationStates[_currentAnimation].MinLife > _life)
            {
                _currentAnimation++;
                if (_currentAnimation < _animationStates.Count)
                {
                    _spriteRenderer.sprite = _animationStates[_currentAnimation].Sprite;
                    _onStateLost?.Invoke();
                }
            }
        }
    }

    public void OnMonsterKilled(Monster monster)
    {
        _attackers.Remove(monster);
    }
}
