using Godot;
using System;

[Tool]
public partial class Interactable : Node2D
{
	private const double Tolerance = 1e-6;

	[Signal]
	public delegate void PlayerNearByEventHandler(Player player);

	[Signal]
	public delegate void PlayerLeftEventHandler(Player player);

	[Signal]
	public delegate void OnInteractEventHandler();

	[Export] public Vector2 SpriteOffset;
	[Export] public float AreaRadius;

	private AnimatedSprite2D _sprite;

	private CollisionShape2D _areaMesh;

	private CircleShape2D _collisionCircle;

	private bool _isEnabled = true;
	
	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
		_sprite = (AnimatedSprite2D)FindChild("AnimatedSprite2D");
		_areaMesh = (CollisionShape2D)FindChild("CollisionShape2D");
		_sprite.Position = SpriteOffset;
		_collisionCircle = (CircleShape2D)_areaMesh.Shape;
		_collisionCircle.Radius = AreaRadius;
		if (Engine.IsEditorHint())
		{
			_sprite.Visible = true;
		}
		else
		{
			_sprite.Visible = false;
		}
	}

	// Called every frame. 'delta' is the elapsed time since the previous frame.
	public override void _Process(double delta)
	{
		if (Engine.IsEditorHint())
		{
			if (_sprite.Position != SpriteOffset) _sprite.Position = SpriteOffset;
			if (Math.Abs(_collisionCircle.Radius - AreaRadius) > Tolerance) _collisionCircle.Radius = AreaRadius;
		}
	}

	public void Interact()
	{
		EmitSignal(SignalName.OnInteract);
	}

	public void Enable()
	{
		_isEnabled = true;
		_sprite.Visible = true;
	}
	public void Disable()
	{
		_isEnabled = false;
		_sprite.Visible = false;
	}
	
	private void _on_area_2d_body_entered(Node2D body)
	{
		if (_isEnabled && body is Player player)
		{
			_sprite.Visible = true;
			EmitSignal(SignalName.PlayerNearBy, player);
		}
	}

	private void _on_area_2d_body_exited(Node2D body)
	{
		if (_isEnabled && body is Player player)
		{
			_sprite.Visible = false;
			EmitSignal(SignalName.PlayerLeft, player);
		}
	}
}
