extends CharacterBody2D
class_name CharacterBase

@export_group("Movement")
@export var movable = true
@export_range(1.0, 999999.9, 0.1) var speed: float = 100.0
@export_group("Combat")
@export var max_health: int = 100
@export_range(0, 999999, 1) var health: int = 100
@export var attack_power: int = 30
@export var KNOCKBACK_POWER: float = 40
@export var KNOCKBACK_RANDOMNESS: float = 50
@export_group("Interactions")
@export var interaction_cutscene: Cutscene
@export_group("Animations")
@export var has_nsfw_animations = false

signal attacked
signal attack_did_hit(other: Area2D, power: int, attack_direction: Vector2)
signal got_hurt(new_health: int)
signal defeated

# Related nodes
@onready var anim_tree: AnimationTree = $AnimationTree
@onready var anim_playback: AnimationNodeStateMachinePlayback = anim_tree["parameters/playback"]

# Cutscene movement
var movement_scripted_by: CutsceneManager = null
var movement_scripted_target: Vector2
var movement_scripted_speed = 0.0

func set_animation_direction(direction: Vector2):
	pass
	
func _physics_process(_delta):
	if movement_scripted_by != null:
		var approach_direction = global_position.direction_to(movement_scripted_target)
		set_animation_direction(approach_direction)
		velocity = movement_scripted_speed * approach_direction
	if movable:
		move_and_slide()
		
func _process(_delta):
	if movement_scripted_by != null:
		var distance_to_target = movement_scripted_target.distance_to(global_position)
		if distance_to_target <= movement_scripted_speed/60.0:
			global_position = movement_scripted_target
			velocity = Vector2.ZERO
			movement_scripted_by.step()
			movement_scripted_by = null
			anim_playback.travel("idle")
	
func _on_animation_tree_animation_finished(anim_name):
	pass
	
func _on_enemy_attack_did_hit(other: Area2D, power: int, attack_direction: Vector2):
	pass
	
func _on_attackbox_area_entered(area: Area2D):
	pass

func _on_cutscene_issued_command(command: CutsceneCommand, manager: CutsceneManager):
	if command is MoveCharacterCommand:
		var target_character = manager.root.get_node(command.target_character)
		if target_character != self:
			return
		movement_scripted_target = command.target_vector if command.target_type == "Vector" else manager.get_node(command.target_node).global_position
		var approach_direction = global_position.direction_to(movement_scripted_target)
		set_animation_direction(approach_direction)
		var move_speed = speed if command.use_character_speed else command.speed
		velocity = move_speed * approach_direction
		movement_scripted_by = manager
		movement_scripted_speed = move_speed
		anim_playback.travel(command.animation_state)
	elif command is PlayCharacterAnimationCommand:
		var target_character = manager.root.get_node(command.target_character)
		if target_character != self:
			return
		anim_playback.travel(command.animation_state)
		manager.step()


func _on_interact_box_area_entered(area: Area2D):
	var parent = area.get_parent()
	if parent is PlayableCharacter:
		parent.interactable_object = self
		parent.interactable_object_cutscene = interaction_cutscene

func _on_interact_box_area_exited(area):
	var parent = area.get_parent()
	if parent is PlayableCharacter:
		if parent.interactable_object_cutscene == interaction_cutscene:
			parent.interactable_object = null
			parent.interactable_object_cutscene = null
