extends Area3D

class_name DraggableObject

signal drag_started
signal drag_ended
signal drag_started_on(obj: DraggableObject)
signal drag_ended_on(obj: DraggableObject)

var mouse_in: bool = false
var dragged: bool = false:
	set(value):
		if dragged != value:
			if value:
				drag_started.emit()
				drag_started_on.emit(self)
				GuiSignalBus.clear_buttons.emit()
				get_viewport().get_camera_3d().start_interaction_seeking(self)
				if button_generator:
					GuiSignalBus.add_buttons.emit(button_generator.get_buttons())
			else:
				drag_ended.emit()
				drag_ended_on.emit(self)
		dragged = value

@export var interactible: Interactible
@export var button_generator: ButtonGenerator

@export var mask: PackedStringArray
var contacted_draggables: Array[DraggableObject]
var filtered_draggables: Array[DraggableObject]

func _ready() -> void:
	area_entered.connect(on_area_entered)
	area_exited.connect(on_area_exited)

func _mouse_enter() -> void:
	mouse_in = true

func _mouse_exit() -> void:
	mouse_in = false

func set_mask(new_mask: PackedStringArray) -> void:
	mask.clear()
	mask.append_array(new_mask)
	filtered_draggables.clear()
	for contacted in contacted_draggables:
		filtered_draggables.append(contacted)

func _process(_delta: float) -> void:
	if dragged == false:
		return
	var camera: Camera3D = get_viewport().get_camera_3d()
	global_position = camera.plane_position

func _input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		if mouse_in and event.pressed:
			dragged = true
		if event.pressed == false:
			dragged = false

func on_area_entered(area: Area3D) -> void:
	if area is DraggableObject:
		contacted_draggables.append(area)
		if is_in_mask(area.get_groups()):
			filtered_draggables.append(area)

func on_area_exited(area: Area3D) -> void:
	if area is DraggableObject:
		contacted_draggables.erase(area)
		if filtered_draggables.has(area):
			filtered_draggables.erase(area)

func is_in_mask(groups: Array[StringName]) -> bool:
	for group in groups:
		if group in mask:
			return true
	return false
