using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// GAME 1303 Tier 2 — A bullet, arrow, fireball, or spit-glob.
///
/// SETUP (make this a prefab)
///  - Sprite + Rigidbody2D (Gravity Scale 0 for straight shots, >0 for lobbed arrows)
///    + Collider2D (Is Trigger ON) + this script.
///  - Team is set by whoever fires it (ProjectileShooter does this).
///  - Hits: Hurtboxes on the other team take Damage; hitting Ground layer destroys it.
///  - Pierce: 0 = destroyed on first hit; 2 = passes through two enemies first.
///
/// Sorcerer's elemental bolts, Blaster's shots, MythoClash's hydra spit and
/// Stardust's buster all use the same script with different sprites/speeds.
/// </summary>
[RequireComponent(typeof(Rigidbody2D), typeof(Collider2D))]
public class Projectile : MonoBehaviour
{
    public int damage = 1;
    public float speed = 12f;
    public float lifetime = 3f;
    [Tooltip("How many hurtboxes it can pass through before dying.")]
    public int pierce = 0;
    public float knockbackForce = 3f;
    public float knockbackUpward = 1f;
    [Tooltip("Layers that stop the projectile (walls, ground).")]
    public LayerMask blockingLayers;
    [Tooltip("Rotate sprite to face travel direction (arrows). Off for round bullets.")]
    public bool faceDirection = true;

    [Header("Effects")]
    public GameObject impactEffectPrefab;
    public UnityEvent<Hurtbox> OnHit;   // ComboCounter.RegisterHit for player shots

    [HideInInspector] public Team team = Team.Player;
    [HideInInspector] public ComboCounter comboSource;   // set by shooter if player

    private Rigidbody2D rb;
    private int hitsLeft;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        GetComponent<Collider2D>().isTrigger = true;
    }

    /// <summary>Called by ProjectileShooter right after Instantiate.</summary>
    public void Launch(Vector2 direction, Team owner, ComboCounter combo = null)
    {
        team = owner;
        comboSource = combo;
        hitsLeft = pierce + 1;
        rb.linearVelocity = direction.normalized * speed;
        if (faceDirection)
            transform.rotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg);
        Destroy(gameObject, lifetime);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Wall?
        if ((blockingLayers.value & (1 << other.gameObject.layer)) != 0)
        {
            Impact();
            return;
        }

        Hurtbox hb = other.GetComponent<Hurtbox>();
        if (hb == null) return;
        if (hb.team == team) return;                          // don't hit friends
        if (hb.team == Team.Neutral || hb.team != team)
        {
            int dmg = damage;
            if (comboSource != null) dmg = Mathf.RoundToInt(damage * comboSource.DamageMultiplier);

            if (hb.ReceiveHit(dmg, transform.position, knockbackForce, knockbackUpward))
            {
                OnHit?.Invoke(hb);
                comboSource?.RegisterHit();
                hitsLeft--;
                if (hitsLeft <= 0) Impact();
            }
        }
    }

    void Impact()
    {
        if (impactEffectPrefab != null)
            Instantiate(impactEffectPrefab, transform.position, Quaternion.identity);
        Destroy(gameObject);
    }
}