AI/ActionSystem/Actions/Staff/ExterminateAction.cs
namespace HC3;

[Icon( "pest_control" )]
public sealed class ExterminateAction : BehaviorTreeAction
{
	private Animal _targetAnimal;
	private Vector3 _lastTargetPosition;
	private const float RepathDistance = 256f;
	private const float CaptureDistance = 100f;

	public override float Score()
	{
		// Find any escaped animal
		_targetAnimal = FindEscapedAnimal();
		if ( !_targetAnimal.IsValid() )
			return 0f;

		return 100f;
	}

	private Animal FindEscapedAnimal()
	{
		// TODO: order by closest (?)
		return Scene.GetAll<Animal>()
			.FirstOrDefault( animal => animal.Tags.Has( "escaped" ) );
	}

	public override void StartAction()
	{
		base.StartAction();

		if ( _targetAnimal == null )
		{
			_targetAnimal = FindEscapedAnimal();
			if ( _targetAnimal == null )
				return;
		}

		_lastTargetPosition = _targetAnimal.WorldPosition;
		Agent.Controller.IsRunning = true;
	}

	public override void StopAction()
	{
		base.StopAction();
		Agent.Controller.IsRunning = false;
		Agent.SetSequenceOverride( null );
	}

	protected override Node BuildTree()
	{
		if ( !_targetAnimal.IsValid() || !_targetAnimal.Tags.Has( "escaped" ) )
			return null;

		return new SequenceNode(
		[
            // 1. Move to the animal, following it if needed
            new FollowTargetNode( Agent, _targetAnimal.GameObject, CaptureDistance, RepathDistance, "Pursuing escaped animal" ),
            
            // 2. Aim at the animal
            new LookAtNode( Agent, _targetAnimal.WorldPosition ),
			new AgentSequenceNode( Agent, "Action_Gun_Aim", 0.5f, "Taking aim" ),
            
            // 3. Shoot the animal with tranquilizer
            new TimedSequenceNode(
				Agent,
				"Action_Gun_Fire",
				0.4f,
				onStart: () => {
                    // Play sound effect
                    Sound.Play( "sounds/gameplay/tranquilizer.sound", Agent.WorldPosition );
                    // Affect the animal
                    _targetAnimal.Tags.Set( "tranquilized", true );
				},
				conditionCheck: () => _targetAnimal.IsValid(),
				reason: "Firing tranquilizer dart",
				icon: "gps_fixed"
			),
            
            // 4. Wait for tranquilizer to take effect and return animal to enclosure
            new TimedActionNode(
				10.0f,
				() => ReturnAnimalToEnclosure( _targetAnimal ),
				() => _targetAnimal.IsValid(),
				"Tranquilizer taking effect",
				"local_hospital"
			)
		] );
	}

	private void ReturnAnimalToEnclosure( Animal animal )
	{
		if ( !animal.IsValid() )
			return;

		// Find an enclosure to return the animal to
		var enclosureArea = Scene.GetAllComponents<AreaTile>()
			.FirstOrDefault( area => area.AreaType == AreaType.Enclosure );

		if ( enclosureArea.IsValid() )
		{
			// Move the animal to that enclosure
			animal.GameObject.WorldPosition = enclosureArea.WorldPosition + Vector3.Up * 10f;
			animal.GameObject.Transform.ClearInterpolation();

			// DebugOverlay.Sphere( new Sphere( enclosureArea.WorldPosition + Vector3.Up * 10f, 32f ), Color.Green, 15f );
		}

		// Remove escaped/tranq tags
		animal.Tags.Set( "escaped", false );
		animal.Tags.Set( "tranquilized", false );
	}

	public override ActionDisplayInfo? GetDisplay()
	{
		if ( !_targetAnimal.IsValid() )
			return new ActionDisplayInfo( "search", "Looking for escaped animals", 0 );

		return null; // The individual nodes will provide their own display info
	}
}