﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Arugula.Games
{
    public class DestructibleObject : MonoBehaviour
    {
        public static DestructibleObject Get(GameObject go)
        {
            return go?.GetComponent<DestructibleObject>();
        }

        public static DestructibleObject Get(Collider c)
        {
            if (c == null)
                return null;

            if (c.GetComponent<DestructibleObject>())
                return c.GetComponent<DestructibleObject>();

            return c.attachedRigidbody?.GetComponent<DestructibleObject>();
        }

        public static DestructibleObject Get(Rigidbody2D rb)
        {
            if (rb == null)
                return null;

            return rb.GetComponent<DestructibleObject>();
        }

        public event Action<DestructibleObject, DamageInfo> OnDamaged = delegate { };
        public event Action<DestructibleObject, DamageInfo> OnHealed = delegate { };
        public event Action<DestructibleObject, DamageInfo> OnDestroyed = delegate { };
        public event Action<DestructibleObject, int> OnHPChanged = delegate { };
        public event Action<DestructibleObject> OnRevived = delegate { };

        public int HP = 0;
        [Range(1, 9999)]
        public int maxHP = 10;
        [Tooltip("Set autoDestroy >= 0 to automatically destroy GameObject after duration")]
        public float autoDestroy = -1;

        public bool Dead => HP <= 0;
        public bool Alive => HP > 0;
        public bool FullHP => HP == maxHP;
        public float NormalizedHP => (float)HP / (float)maxHP;

        internal virtual void Start()
        {
            if (HP == 0 || HP > maxHP)
                HP = maxHP;
        }

        //TODO: handle relevant information about what/who/where did the damage
        public void Damage(DamageInfo info)
        {
            if (Dead)
                return;

            HP -= info.amount;

            if (HP < 0)
                HP = 0;

            OnDamaged(this, info);
            OnHPChanged(this, HP);

            if (HP <= 0)
            {
                OnDestroyed(this, info);

                if (autoDestroy >= 0)
                    Destroy(gameObject, autoDestroy);
            }
        }

        public void Heal(DamageInfo info)
        {
            if (Dead)
                return;

            HP += info.amount;

            if (HP > maxHP)
                HP = maxHP;

            OnHealed(this, info);
            OnHPChanged(this, HP);
        }

        public void Revive()
        {
            if (Alive)
                return;

            HP = 1;
            OnHPChanged(this, HP);
            OnRevived(this);
        }
    }
}