class_name OrbitalCamera extends Node3D

const POSITION_ACCELERATION := 4.0
const BASIS_ACCELERATION := 4.0
const TARGETER_ACCELERATION := 8.0

@export var target: Node3D
@export var offset := Vector3(0, 1, 0)

@export var angular_speed := 0.007

var target_basis := Basis.IDENTITY

@onready var pivot: Node3D = %Pivot
@onready var camera: Camera3D = %Camera
@onready var targeter: Node3D = %Targeter

static var scene := preload("res://src/ui/camera/orbital_camera/orbital_camera.tscn")


func _physics_process(delta: float) -> void:
	var up := Vector3.UP
	# If target is a game ball, realign to gravity
	if is_instance_valid(target) and target is GameBall:
		up = -(target as GameBall).current_gravity.normalized()
		var right := up.cross(global_basis.z).normalized()
		var forward := right.cross(up).normalized()
		target_basis = Basis(right, up, forward)

	# Slerp to basis
	global_basis = global_basis.slerp(target_basis, delta * BASIS_ACCELERATION)

	# Update position
	global_position = global_position.lerp(
		target.global_position + offset, delta * POSITION_ACCELERATION
	)

	# Update rotation
	#camera.look_at(target.global_position, up)
	targeter.look_at(target.global_position, up)
	camera.global_basis = camera.global_basis.slerp(
		targeter.global_basis.orthonormalized(), delta * TARGETER_ACCELERATION
	)

	# Update phase angle
	pivot.rotation.y += angular_speed


static func create(_target: Node3D) -> OrbitalCamera:
	var instance: OrbitalCamera = scene.instantiate()
	instance.target = _target
	return instance
