using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// GAME 1303 Tier 4 — A lever, button, or pressure plate that drives something else
/// (usually a Door). Anabasis, Apep's Trial, Zap Attack, Spark of Corruption.
///
/// SETUP
/// 1. Sprite + Collider2D (Is Trigger) + this script.
/// 2. Activation:
/// Touch – flips when the player walks into it.
/// Stand – ON while something stands on it, OFF when they leave
/// (a pressure plate; a crate counts if Any Rigidbody is ticked).
/// Hit – needs a Tier 2 attack. Add a Hurtbox child (Team Neutral) and a
/// Health (1 HP, Destroy On Death off), then wire Health.OnDamaged
/// -> PuzzleSwitch.Activate.
/// 3. One Shot: once on, stays on.
/// 4. Wire OnActivated -> Door.Open (or anything else). OnDeactivated for plates.
/// 5. Sprites: On/Off sprites swap automatically if assigned.
///
/// Several switches into one door: put a SwitchGroup on the door's parent (below).
/// </summary>
[RequireComponent(typeof(Collider2D))]
public class PuzzleSwitch : MonoBehaviour
{
public enum Activation { Touch, Stand, Hit }
public Activation activation = Activation.Touch;
public bool oneShot = true;
[Tooltip("Stand mode: crates and other rigidbodies can hold it down, not just the player.")]
public bool anyRigidbody = false;
[Header("Look")]
public SpriteRenderer spriteRenderer;
public Sprite offSprite;
public Sprite onSprite;
public string onSfx = "switch_on";
public string offSfx = "";
[Header("Events")]
public UnityEvent OnActivated;
public UnityEvent OnDeactivated;
public bool IsOn { get; private set; }
private int standingCount;
void Reset() { GetComponent<Collider2D>().isTrigger = true; }
void Awake()
{
if (spriteRenderer == null) spriteRenderer = GetComponent<SpriteRenderer>();
Refresh();
}
void OnTriggerEnter2D(Collider2D other)
{
if (!Accepts(other)) return;
if (activation == Activation.Touch) Activate();
else if (activation == Activation.Stand) { standingCount++; if (standingCount == 1) SetState(true); }
}
void OnTriggerExit2D(Collider2D other)
{
if (activation != Activation.Stand || !Accepts(other)) return;
standingCount = Mathf.Max(0, standingCount - 1);
if (standingCount == 0 && !oneShot) SetState(false);
}
bool Accepts(Collider2D other)
{
if (other.CompareTag("Player")) return true;
return anyRigidbody && other.attachedRigidbody != null;
}
/// <summary>Flip it on (or toggle if not one-shot). Wire attacks / Interactables here.</summary>
public void Activate()
{
if (IsOn && oneShot) return;
SetState(oneShot || !IsOn);
}
public void SetState(bool on)
{
if (on == IsOn) return;
IsOn = on;
Refresh();
string sfx = on ? onSfx : offSfx;
if (!string.IsNullOrEmpty(sfx)) AudioManager.Instance?.PlaySFX(sfx);
if (on) OnActivated?.Invoke(); else OnDeactivated?.Invoke();
}
void Refresh()
{
if (spriteRenderer == null) return;
Sprite s = IsOn ? onSprite : offSprite;
if (s != null) spriteRenderer.sprite = s;
}
}