class_name MainCamera
extends Camera3D

@export var _height_offset: float = 0.5
@export var _distance: float = 50
@export var _angle_degrees: Vector3 = Vector3(-35, -45, 0)
@export var _aim_offset_factor_mouse: float = 0.2
@export var _aim_offset_factor_controller: float = 0.5
@export var _aim_damping: float = 1

var _player_offsets: Dictionary


func _ready() -> void:
	Referencer.main_camera = self


func _process(delta: float) -> void:
	var follow_position: Vector3 = Vector3.ZERO
	for player in Referencer.players:
		follow_position += _follow(player, delta)
	follow_position /= Referencer.players_count

	global_rotation_degrees = _angle_degrees
	global_position = (
		follow_position + Vector3.UP * _height_offset + transform.basis.z * _distance
	)


func _follow(player: Player, delta: float) -> Vector3:
	var id := player.get_instance_id()
	if not _player_offsets.has(id):
		_player_offsets[id] = {"floor_height": 0, "aim_offset": Vector3.ZERO}

	var player_offset: Dictionary = _player_offsets[id]

	var player_position := player.global_position
	if player.is_on_floor():
		player_offset["floor_height"] = player_position.y
	player_position.y = player_offset["floor_height"] + Projectile.HEIGHT

	if player.input_mode_is(Inputer.Mode.KB_MOUSE):
		player_offset["aim_offset"] = player.aiming.aim_offset
	elif (
		player.input_mode_is(Inputer.Mode.CONTROLLER) and Referencer.players_count == 1
	):
		var new_aim_offset := (
			Vector3.ZERO
			if player.aiming.aim_input.length() == 0
			else player.aiming.aim_offset
		)
		player_offset["aim_offset"] = player_offset["aim_offset"].lerp(
			new_aim_offset, _aim_damping * delta
		)
	else:
		player_offset["aim_offset"] = Vector3.ZERO

	var follow_position := (
		player_position
		+ (
			player_offset["aim_offset"] as Vector3
			* (
				_aim_offset_factor_mouse
				if player.input_mode_is(Inputer.Mode.KB_MOUSE)
				else _aim_offset_factor_controller
			)
		)
	)

	Debugger.circle("follow_position" + str(player.name), follow_position)

	return follow_position
