extends CharacterBody3D

const SPEED := 4.0
const GRAVITY := 9.8
const MOUSE_SENSITIVITY := 0.002
const INTERACT_DISTANCE := 2.5

var _camera: Camera3D
var _raycast: RayCast3D


func _ready() -> void:
	_camera = get_node("Camera3D") as Camera3D
	_raycast = _camera.get_node("InteractRay") as RayCast3D
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED


func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity.y -= GRAVITY * delta

	var input_dir := Vector2(
		Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
		Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
	)
	var move_dir := (transform.basis.x * input_dir.x + -transform.basis.z * input_dir.y).normalized()
	velocity.x = move_dir.x * SPEED
	velocity.z = move_dir.z * SPEED
	move_and_slide()


func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouseMotion:
		rotate_y(-event.relative.x * MOUSE_SENSITIVITY)
		_camera.rotate_x(-event.relative.y * MOUSE_SENSITIVITY)
		_camera.rotation.x = clampf(_camera.rotation.x, -PI / 2.0, PI / 2.0)
	elif event.is_action_pressed("interact"):
		_try_interact()
	elif event.is_action_pressed("ui_cancel"):
		if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
			Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
		else:
			Input.mouse_mode = Input.MOUSE_MODE_CAPTURED


func _try_interact() -> void:
	if not _raycast.is_colliding():
		return
	var target := _raycast.get_collider()
	if target != null and target.has_method("interact"):
		target.interact(NetworkManager.my_id)
