## HoldableItem — Node2D that can be held in a Character's HandLeft or HandRight slot.
## Attach DragDropComponent as a child. On drag_released scans "characters" group for
## the nearest free hand slot within HAND_SLOT_RADIUS.
class_name HoldableItem extends Node2D

signal item_picked_up(item: HoldableItem)
signal item_placed(item: HoldableItem)

const HAND_SLOT_RADIUS: float = 60.0

@export var item_id: String = ""


func _ready() -> void:
	var drag: DragDropComponent = get_node_or_null("DragDropComponent") as DragDropComponent
	if drag != null:
		drag.drag_picked_up.connect(_on_drag_picked_up)
		drag.drag_released.connect(_on_drag_released)


func _on_drag_picked_up(_pos: Vector2) -> void:
	if is_in_hand_slot():
		_detach_from_hand_slot()
	item_picked_up.emit(self)


func _on_drag_released(_pos: Vector2) -> void:
	var result: Array = _find_nearest_free_hand_slot()
	if not result.is_empty():
		var character: Character = result[0] as Character
		var hand: String = result[1] as String
		character.attach_item(hand, self)
	item_placed.emit(self)


func is_in_hand_slot() -> bool:
	var p: Node = get_parent()
	if p == null:
		return false
	return p.name == "HandLeft" or p.name == "HandRight"


func _detach_from_hand_slot() -> void:
	var hand_slot: Node = get_parent()
	var character: Character = hand_slot.get_parent() as Character
	if character == null:
		return
	var hand: String = "left" if hand_slot.name == "HandLeft" else "right"
	character.detach_item(hand)


func _find_nearest_free_hand_slot() -> Array:
	var best_dist: float = HAND_SLOT_RADIUS
	var best_character: Character = null
	var best_hand: String = ""
	for node: Node in get_tree().get_nodes_in_group("characters"):
		var character: Character = node as Character
		if character == null:
			continue
		for hand: String in ["left", "right"]:
			if not character.is_hand_free(hand):
				continue
			var slot: Node2D = character.get_node_or_null("Hand" + hand.capitalize()) as Node2D
			if slot == null:
				continue
			var dist: float = global_position.distance_to(slot.global_position)
			if dist < best_dist:
				best_dist = dist
				best_character = character
				best_hand = hand
	if best_character == null:
		return []
	return [best_character, best_hand]
