extends Camera3D

@export var height: float = 18.0
@export var horizontal_distance: float = 18.0
@export var horizontal_angle_deg: float = 45.0
@export var ortho_size: float = 15.0
@export var ortho_size_max: float = 40.0

const _FLASH_DURATION: float = 0.30

var _shake_amount: float = 0.0
var _shake_decay: float = 0.0
var _flash_timer: float = 0.0
var _flash_rect: ColorRect = null
var _target_size: float = 0.0


func _ready() -> void:
	set_as_top_level(true)
	projection = PROJECTION_ORTHOGONAL
	_target_size = ortho_size
	size = ortho_size
	_setup_flash()


func _setup_flash() -> void:
	var canvas := CanvasLayer.new()
	canvas.layer = 20
	add_child(canvas)
	_flash_rect = ColorRect.new()
	_flash_rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
	_flash_rect.color = Color(1.0, 0.25, 0.2, 0.0)
	_flash_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
	canvas.add_child(_flash_rect)


func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed("zoom_in"):
		_target_size = clamp(_target_size / 1.2, ortho_size, ortho_size_max)
	if event.is_action_pressed("zoom_out"):
		_target_size = clamp(_target_size * 1.2, ortho_size, ortho_size_max)


func _process(delta: float) -> void:
	size = lerpf(size, _target_size, delta * 10.0)
	var angle_rad := deg_to_rad(horizontal_angle_deg)
	var offset := Vector3(
		sin(angle_rad) * horizontal_distance,
		height,
		cos(angle_rad) * horizontal_distance,
	)
	var target := get_parent() as Node3D
	global_position = target.global_position + offset
	look_at(target.global_position, Vector3.UP)

	if _shake_amount > 0.005:
		global_position += Vector3(
			randf_range(-_shake_amount, _shake_amount),
			randf_range(-_shake_amount * 0.25, _shake_amount * 0.25),
			randf_range(-_shake_amount, _shake_amount),
		)
		_shake_amount = move_toward(_shake_amount, 0.0, _shake_decay * delta)

	if _flash_timer > 0.0:
		_flash_timer = maxf(0.0, _flash_timer - delta)
		_flash_rect.color.a = (_flash_timer / _FLASH_DURATION) * 0.6
	else:
		_flash_rect.color.a = 0.0


func trigger_hit(strength: float) -> void:
	_shake_amount = strength * 0.5
	_shake_decay = _shake_amount / 0.4
	_flash_timer = _FLASH_DURATION
