extends Area2D

signal bullet_fired(pos, angle)
signal ship_destroyed

const SCREEN = Vector2(640, 640)

@export var thrust_power:   float = 280.0
@export var rotation_speed: float = 3.2
@export var friction:       float = 0.98
@export var shoot_cooldown: float = 0.25
@export var max_speed:      float = 420.0

var velocity:      Vector2 = Vector2.ZERO
var _alive:        bool    = true
var _shoot_timer:  float   = 0.0
var _invincible:   float   = 0.0   # seconds of invincibility after respawn
var _rapid_timer:  float   = 0.0   # rapid fire power-up
var _shield_timer: float   = 0.0   # shield power-up
var _thrusting:    bool    = false

@onready var sprite:        AnimatedSprite2D = $Sprite
@onready var shield_sprite: Sprite2D         = $ShieldSprite
@onready var col:           CollisionShape2D = $Col


func _ready() -> void:
	add_to_group("ship")
	shield_sprite.hide()
	sprite.play("idle")


func _process(delta: float) -> void:
	if not _alive:
		return

	_shoot_timer  = max(0.0, _shoot_timer  - delta)
	_invincible   = max(0.0, _invincible   - delta)
	_rapid_timer  = max(0.0, _rapid_timer  - delta)
	_shield_timer = max(0.0, _shield_timer - delta)

	# Flash when invincible
	modulate.a = 0.4 if (_invincible > 0 and int(_invincible * 10) % 2 == 0) else 1.0

	# Shield visual
	shield_sprite.visible = _shield_timer > 0

	# Rotate
	if Input.is_key_pressed(KEY_LEFT)  or Input.is_key_pressed(KEY_A):
		rotation -= rotation_speed * delta
	if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D):
		rotation += rotation_speed * delta

	# Thrust
	_thrusting = Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_W)
	if _thrusting:
		var dir = Vector2(sin(rotation), -cos(rotation))
		velocity += dir * thrust_power * delta
		velocity  = velocity.limit_length(max_speed)
		sprite.play("thrust")
	else:
		sprite.play("idle")

	# Friction / drag in space
	velocity *= pow(friction, delta * 60)

	# Move
	position += velocity * delta

	# Screen wrap
	position.x = wrapf(position.x, -20, SCREEN.x + 20)
	position.y = wrapf(position.y, -20, SCREEN.y + 20)

	# Shoot
	var cooldown = shoot_cooldown * (0.3 if _rapid_timer > 0 else 1.0)
	if _shoot_timer <= 0 and (
		Input.is_key_pressed(KEY_SPACE) or Input.is_key_pressed(KEY_Z)
	):
		_shoot_timer = cooldown
		bullet_fired.emit(position + Vector2(sin(rotation), -cos(rotation)) * 22, rotation)


func apply_shield(duration: float = 6.0) -> void:
	_shield_timer = duration


func apply_rapid(duration: float = 6.0) -> void:
	_rapid_timer = duration


func has_shield() -> bool:
	return _shield_timer > 0


func die() -> void:
	if not _alive or _invincible > 0:
		return
	if _shield_timer > 0:
		_shield_timer = 0.0   # shield absorbs one hit
		_invincible = 1.5
		return
	_alive = false
	ship_destroyed.emit()
	hide()
	col.set_deferred("disabled", true)


func respawn(pos: Vector2) -> void:
	position   = pos
	velocity   = Vector2.ZERO
	rotation   = 0.0
	_alive     = true
	_invincible = 3.0
	show()
	col.set_deferred("disabled", false)
	sprite.play("idle")
