@icon("res://components/Cursor/mouse-pointer-2.svg")
extends Base

@onready var mouse_control = $"MouseControl"
@onready var sprite_2d: Sprite2D = $MouseControl/Sprite2D
@onready var audio_stream_player: AudioStreamPlayer = $AudioStreamPlayer
@onready var audio_stream_player_2: AudioStreamPlayer = $AudioStreamPlayer2
@onready var audio_stream_player_3: AudioStreamPlayer = $AudioStreamPlayer3

const CURSOR_UI = preload("res://components/Cursor/hover-1.png")
const CURSOR_HOLD = preload("res://components/Cursor/grab-1.png")
const CURSOR = preload("res://components/Cursor/normal-1.png")
const CREATURE = preload("res://src/Creature.tscn")
var rotation_tween

var cursor_tween
var hovered_objects = 0
var holding = false
var grabbed_creature
var signal_object
var original_window
var original_position
var timer = 0
var hover_timer = 0

func _ready() -> void:
	Persister.data_persisted.connect(_on_data_persisted)
	Triggerer.listen("grab_creature", _on_grab_creature)
	Triggerer.listen("hovered", _on_hovered)
		
	for child in get_parent().get_children():
		if child.is_in_group("mouse_signals"):
			signal_object = child


func _on_hovered(_data):
	hover_timer = 0.125


func _on_grab_creature(data):
	grabbed_creature = CREATURE.instantiate()
	grabbed_creature.key = data.creature
	grabbed_creature.held = true
	grabbed_creature.tiles = data.tiles
	grabbed_creature.tiled = data.tiled
	mouse_control.add_child(grabbed_creature)
	grabbed_creature.position = Vector2(0, 0)
	holding = true
	
	original_window = data.old_window
	original_position = data.old_position
	
	if get_window().get_window_id() == 0:
		audio_stream_player_3.play()

func let_go():
	if holding and grabbed_creature:
		if get_window().get_window_id() == 0 and not Persister.get_value("hovered"):
			var new_creature = CREATURE.instantiate()
			new_creature.key = grabbed_creature.key
			new_creature.position = original_position
			original_window.add_child(new_creature)
			audio_stream_player_2.play()
		
		if get_window().get_window_id() == 0:
			Persister.persist_data("grabbing", false)
		
		if signal_object and signal_object.mouse_in_window:
			if get_window().name == "CreatureWindow":
				var new_creature = CREATURE.instantiate()
				new_creature.key = grabbed_creature.key
				new_creature.global_position = grabbed_creature.global_position
				get_window().add_child(new_creature)
				audio_stream_player_2.play()
				
				if grabbed_creature.tiled:
					original_window.remove_tiles(grabbed_creature.tiles)
			else:
				if not get_window().attempt_place(grabbed_creature.key, mouse_control.position, grabbed_creature.tiles):
					var new_creature = CREATURE.instantiate()
					new_creature.key = grabbed_creature.key
					new_creature.position = original_position
					new_creature.tiles = grabbed_creature.tiles
					new_creature.tiled = grabbed_creature.tiled
					original_window.add_child(new_creature)
					audio_stream_player.play()
				else:
					audio_stream_player_2.play()
					if grabbed_creature.tiled:
						original_window.remove_tiles(grabbed_creature.tiles)
		grabbed_creature.queue_free()
		grabbed_creature = null
	
	
	
	holding = false

func _on_release():
	let_go()
	Triggerer.trigger("released")
	
	var overlapping_areas = mouse_control.get_overlapping_areas()
	overlapping_areas.sort_custom(func(a, b):
		return a.z_index > b.z_index
	)
	
	for area in overlapping_areas:
		if area.has_method("_on_released"):
			var current_node = area
			var hidden = false
			while current_node:
				if "modulate" in current_node:
					if current_node.modulate.a < 1:
						hidden = true
						break
				current_node = current_node.get_parent()
			
			if hidden:
				continue
			
			if not area._on_released():
				break


func _on_click():
	var overlapping_areas = mouse_control.get_overlapping_areas()
	overlapping_areas.sort_custom(func(a, b):
		return a.z_index > b.z_index
	)
	
	for area in overlapping_areas:
		if area.has_method("_on_clicked"):
			var current_node = area
			var hidden = false
			while current_node:
				if "modulate" in current_node:
					if current_node.modulate.a < 1:
						hidden = true
						break
				if "visible" in current_node:
					if not current_node.visible:
						hidden = true
						break
				current_node = current_node.get_parent()
			
			if hidden:
				continue
			
			if not area._on_clicked():
				break


func _process(delta):
	if Input.is_action_just_released("left_click"):
		_on_release()
	if Input.is_action_just_pressed("left_click"):
		_on_click()
	#Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
	mouse_control.position = mouse_control.get_global_mouse_position()
	
	if timer > 0:
		timer -= delta
		if timer <= 0:
			let_go()
	
	if hover_timer > 0:
		hover_timer -= delta
		timer = 0
	
	if not Input.is_action_pressed("left_click"):
		sprite_2d.rotation = move_toward(sprite_2d.rotation, 0, delta)
		sprite_2d.scale = sprite_2d.scale.move_toward(Vector2.ONE, delta)
	else:
		sprite_2d.scale = sprite_2d.scale.move_toward(Vector2.ONE * 0.9, delta * 2)
		sprite_2d.rotation = move_toward(sprite_2d.rotation, -0.1, delta * 2)

func _on_mouse_control_area_entered(area):
	if area.has_method("_on_hovered"):
		var current_node = area
		var hidden = false
		while current_node:
			if "visible" in current_node:
				if not current_node.visible:
					hidden = true
					break
			current_node = current_node.get_parent()
		
		if not hidden:
			area._on_hovered()
			hovered_objects += 1
			
			_update_cursor()


func _on_mouse_control_area_exited(area):
	if area.has_method("_on_unhovered"):
		var current_node = area
		var hidden = false
		while current_node:
			if "visible" in current_node:
				if not current_node.visible:
					hidden = true
					break
			current_node = current_node.get_parent()
		
		if not hidden:
			area._on_unhovered()
			hovered_objects -= 1
			
			_update_cursor()


func _update_cursor():
	if holding:
		sprite_2d.texture = CURSOR_HOLD
	if hovered_objects:
		sprite_2d.texture = CURSOR_UI
	else:
		sprite_2d.texture = CURSOR