@tool

extends Area2D
class_name StickyNote
var sibling
var shift_tween
var modulate_tween

signal transform_tween_finished

@export var text: String = "" :
	set (value):
		if is_inside_tree() or Engine.is_editor_hint():
			$Content/Label.text = value
			$Content/BackgroundSprite.frame = text.hash() % $Content/BackgroundSprite.sprite_frames.get_frame_count($Content/BackgroundSprite.animation)
		text = value
		

@export var shift_by: Vector2 = Vector2(-32, 0)
@export_color_no_alpha var highlight_color: Color = Color(1.5, 1.5, 1.5)
@export var highlighted: bool = false:
	set(highlight):
		if highlight != highlighted:
			highlighted = highlight

			if is_inside_tree() and is_node_ready():
				if modulate_tween: modulate_tween.kill()
				if shift_tween: shift_tween.kill()
				if highlighted:
					modulate_tween = get_tree().create_tween()
					modulate_tween.tween_property(self, "modulate", highlight_color, 0.1)
					shift_tween = get_tree().create_tween()
					shift_tween.tween_property($Content, "position", shift_by, 0.2)
				else:
					modulate_tween = get_tree().create_tween()
					modulate_tween.tween_property(self, "modulate", Color(1, 1, 1), 0.3)
					shift_tween = get_tree().create_tween()
					shift_tween.tween_property($Content, "position", Vector2.ZERO, 0.5)
			else:
				if highlighted:
					modulate = Color(1, 1, 1)
				else:
					modulate = Color(1, 1, 1)

@export var voice_line: AudioStream = null
@export var is_dragable: bool = false
@onready var base_rotation = rotation
@onready var base_scale = scale
var is_dragged: bool = false:
	set(dragged):
		is_dragged = dragged
		z_index = int(dragged)

var initial_drag_position: Vector2
var mouse_diff: Vector2

@onready var diameter = $CollisionShape2D.shape.height
@export_range(1.0, 10.0) var bounce_speed: float = 8
var on_board: bool = false
var attached_to: Node = null

func _ready() -> void:
	
	$Content/Label.text = self.text
	$Content/BackgroundSprite.frame = text.hash() % $Content/BackgroundSprite.sprite_frames.get_frame_count($Content/BackgroundSprite.animation)
	
	$Content/Label.theme = State.current_main_theme
	State.theme_changed.connect(func change_theme(new_theme): $Content/Label.theme = new_theme)

func replace_with(sticky_note: StickyNote):
	self.text = sticky_note.text
	self.voice_line = sticky_note.voice_line
	self.sibling = sticky_note.sibling
	self.name = sticky_note.name
	for group in self.get_groups():
		self.remove_from_group(group)
	for group in sticky_note.get_groups():
		self.add_to_group(group)

func _process(delta: float) -> void:
	if get_overlapping_areas().size() > 0 and is_dragable and on_board:
		for area in get_overlapping_areas():
			if area is Card or area is CardCollider:
				if area is CardCollider:
					position += area.direction * delta
				elif not area.highlighted or self.highlighted: 
					var diff:Vector2 = position - area.position
					position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60))
	
	_move_sticky_note()

func _on_focus_entered():
	print(self, "is focused")

func _on_focus_exited():
	print(self, "is not focused")

func _on_mouse_entered():
	if not Input.is_action_pressed("mouse_left"):
		highlighted = true
		if "handle_hover" in owner:
			owner.handle_hover(self)

func _on_mouse_exited():
	highlighted = false
	if is_sticky_note_attached() and "check_hover" in get_parent():
		get_parent().check_hover()

func _on_input_event(viewport, event, shape_idx):
		
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_RIGHT:
			if "handle_mouse_button" in owner:
				mouse_diff = get_viewport().get_mouse_position()
				initial_drag_position = global_position
				owner.handle_mouse_button(self, event)

func _move_sticky_note():
	if is_dragged:
		position = initial_drag_position + get_viewport().get_mouse_position() - mouse_diff

func is_sticky_note_attached() -> bool:
	# there is probably a nicer way to do this
	return self.get_parent().get_parent() is Card

func tween_transform_to(target: Transform2D):
	var transform_tween: Tween = create_tween()
	transform_tween.tween_property(self, "transform", target, 0.25)
	await transform_tween.finished
	emit_signal("transform_tween_finished")

func reset_drag():
	if attached_to != null:
		attached_to.reclaim_sticky_note()
