class_name DeployedUnit extends Node2D

enum UnitState { ALIVE, DEAD }

@export var unit: Unit

var current_stats: DeployedUnitStats
var tactics: Array[CombatTactic] = []
var state: UnitState = UnitState.ALIVE

var _sprite: AnimatedSprite2D
var _previous_position: Vector2

signal unit_selected_changed(deployed: DeployedUnit, selected: bool)
signal unit_allegiance_changed(deployed: DeployedUnit, allegiance: UnitAllegiance)
signal unit_died(deployed: DeployedUnit)

func _ready() -> void:
	current_stats = DeployedUnitStats.from_unit_stats(unit.stats)
	tactics = unit.tactics.duplicate()
	_append_builtin_tactics()
	unit_allegiance_changed.emit(self, unit.allegiance)
	_previous_position = position
	_setup_appearance()

func _setup_appearance() -> void:
	_sprite = get_node_or_null("AnimatedSprite2D") as AnimatedSprite2D
	if not _sprite:
		return
	var sprite_frames: SpriteFrames = unit.appearance.deployed_sprite_sheet if unit.appearance else null
	if not sprite_frames:
		return
	_sprite.sprite_frames = sprite_frames
	_sprite.play("idle")

func _physics_process(_delta: float) -> void:
	if not _sprite or not _sprite.sprite_frames:
		return
	var delta_pos := position - _previous_position
	_previous_position = position
	if delta_pos.length_squared() < 0.01:
		if _sprite.animation != &"idle":
			_sprite.play("idle")
		return
	var anim: StringName
	if absf(delta_pos.x) >= absf(delta_pos.y):
		anim = &"right" if delta_pos.x > 0 else &"left"
	else:
		anim = &"down" if delta_pos.y > 0 else &"up"
	if _sprite.animation != anim:
		_sprite.play(anim)

func _append_builtin_tactics() -> void:
	var attack := AttackCombatTactic.new()
	attack.tactic_name = "Attack"
	attack.tactic_range = UnitMatchingCombatTacticRange.new()
	tactics.append(attack)

	var defend := DefendCombatTactic.new()
	defend.tactic_name = "Defend"
	defend.tactic_range = AnyCombatTacticRange.new()
	tactics.append(defend)

func set_selected(selected: bool) -> void:
	unit_selected_changed.emit(self, selected)

func is_alive() -> bool:
	return state == UnitState.ALIVE

func take_damage(amount: int) -> void:
	if state != UnitState.ALIVE:
		return
	current_stats.current_hp -= amount
	if current_stats.current_hp <= 0:
		current_stats.current_hp = 0
		_die()

func _die() -> void:
	state = UnitState.DEAD
	unit_died.emit(self)
	queue_free()
