Story/ActionTrigger.cs
namespace Opium;

public interface ITriggerable
{
	public void Trigger();
}

[EditorHandle( "ui/gizmos/action.png" )]
public partial class ActionTrigger : Component, Component.ITriggerListener
{
	/// <summary>
	/// A list of triggers that need to be activated before this one can be.
	/// </summary>
	[Property] public List<ActionTrigger> RequiredTriggers { get; set; }

	/// <summary>
	/// A list of important markers that we'll pass to ActionGraph.
	/// </summary>
	public IEnumerable<ObjectMarker> Markers => Components.GetAll<ObjectMarker>( FindMode.EverythingInSelfAndDescendants );

	[Property, ReadOnly] public bool Activated { get; set; }

	[Property] public Action<IEnumerable<ObjectMarker>> OnActivate { get; set; }

	[Property] public List<GameObject> Triggerables { get; set; } = new();

	/// <summary>
	/// An actor if we found one.
	/// </summary>
	public Actor Actor { get; set; }

	public void OnTriggerEnter( Collider other )
	{
		if ( Activated ) return;

		var actor = other.Components.Get<Actor>( FindMode.EverythingInSelfAndAncestors );

		// If we don't have any requirements, or we match ALL of them.
		if ( actor is not null && ( RequiredTriggers.Count < 1 || RequiredTriggers.All( x => x.Activated ) ) )
		{
			Actor = actor;
			Activate();
		}
	}

	protected override void DrawGizmos()
	{
		Gizmo.Transform = new();

		var baseColor = Activated ? Color.Red : Color.Cyan;

		foreach ( var obj in Components.GetAll<Collider>() )
		{
			foreach ( var shape in obj.KeyframeBody.Shapes )
			{
				var body = shape.Body;
				var bounds = body.GetBounds();

				Gizmo.Draw.Color = baseColor.WithAlpha( 0.8f );
				Gizmo.Draw.LineBBox( bounds.Grow( 1f ) );
				Gizmo.Draw.Color = baseColor.WithAlpha( 0.2f );
				Gizmo.Draw.SolidBox( bounds );
				Gizmo.Hitbox.BBox( bounds );
			}
		}

		foreach ( var child in GameObject.Children )
		{
			Gizmo.Draw.Color = baseColor.WithAlpha( 0.8f );
			Gizmo.Draw.Line( GameObject.Transform.Position + Vector3.Up * 2f, child.Transform.Position );
		}
	}

	void Triggers()
	{
		foreach ( var go in Triggerables )
		{
			var triggerable = go?.Components.Get<ITriggerable>();
			if ( triggerable is not null ) triggerable.Trigger();
		}
	}

	protected virtual void Activate()
	{
		Triggers();

		OnActivate?.Invoke( Markers );
		Activated = true;
	}

	public void OnTriggerExit( Collider other )
	{
	}
}