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

/// <summary>
/// GAME 1303 Tier 5 — Drops a treat somewhere valid, and drops another when it's eaten.
/// Weenie Maze. (Also fine for any "collect the thing that keeps reappearing" game.)
///
/// SETUP
///  1. Empty GameObject + this script.
///  2. Treat Prefab: sprite + trigger Collider2D + Tier 1 Collectible (with an ItemType
///     asset like "Treat"). This spawner listens for it being destroyed and makes another.
///  3. Spawn Area: either
///       - drag in a BoxCollider2D (trigger) covering the play field, or
///       - leave it empty and set Area Size manually (centred on this object).
///  4. Blocking Layers: walls AND the snake body layer, so treats never appear inside a
///     wall or under the dog. Attempts is how many random cells it tries before giving up.
///  5. Snap To Grid + Cell Size should match the GridMover so treats land on cell centres.
///  6. Max Active: 1 for classic snake; more for a maze scattered with treats.
/// </summary>
public class TreatSpawner : MonoBehaviour
{
    public GameObject treatPrefab;
    public int maxActive = 1;
    public float respawnDelay = 0f;

    [Header("Area")]
    public BoxCollider2D spawnArea;
    public Vector2 areaSize = new Vector2(16f, 10f);

    [Header("Placement")]
    public bool snapToGrid = true;
    public float cellSize = 1f;
    public LayerMask blockingLayers;
    [Tooltip("Keep at least this far from the player when spawning.")]
    public float minDistanceFromPlayer = 2f;
    public int attempts = 40;

    [Header("Events")]
    public UnityEvent<Vector3> OnTreatSpawned;
    public UnityEvent OnSpawnFailed;   // board is full — usually a win!

    private readonly List<GameObject> active = new List<GameObject>();
    private Transform player;
    private float timer;

    void Start()
    {
        var p = GameObject.FindGameObjectWithTag("Player");
        if (p != null) player = p.transform;
        for (int i = 0; i < maxActive; i++) SpawnOne();
    }

    void Update()
    {
        active.RemoveAll(t => t == null);
        if (active.Count >= maxActive) return;

        timer -= Time.deltaTime;
        if (timer <= 0f)
        {
            SpawnOne();
            timer = respawnDelay;
        }
    }

    public void SpawnOne()
    {
        if (treatPrefab == null) return;

        Vector2 centre = spawnArea != null ? (Vector2)spawnArea.bounds.center : (Vector2)transform.position;
        Vector2 size = spawnArea != null ? (Vector2)spawnArea.bounds.size : areaSize;

        for (int i = 0; i < attempts; i++)
        {
            Vector2 p = centre + new Vector2(
                Random.Range(-size.x * 0.5f, size.x * 0.5f),
                Random.Range(-size.y * 0.5f, size.y * 0.5f));

            if (snapToGrid)
                p = new Vector2(Mathf.Round(p.x / cellSize) * cellSize, Mathf.Round(p.y / cellSize) * cellSize);

            if (Physics2D.OverlapBox(p, Vector2.one * cellSize * 0.8f, 0f, blockingLayers) != null) continue;
            if (player != null && Vector2.Distance(p, player.position) < minDistanceFromPlayer) continue;

            var treat = Instantiate(treatPrefab, p, Quaternion.identity);
            active.Add(treat);
            OnTreatSpawned?.Invoke(p);
            return;
        }

        OnSpawnFailed?.Invoke();
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = new Color(1f, 0.9f, 0.3f, 0.4f);
        Vector3 c = spawnArea != null ? spawnArea.bounds.center : transform.position;
        Vector3 s = spawnArea != null ? spawnArea.bounds.size : (Vector3)areaSize;
        Gizmos.DrawWireCube(c, s);
    }
}