extends Node3D

@export var followedEntity: Node3D
@export var controlledEntity: Puppet

var xr_interface: XRInterface

func _ready():
	xr_interface = XRServer.find_interface("OpenXR")
	if xr_interface and xr_interface.is_initialized():
		print("OpenXR initialized successfully")

		# Turn off v-sync!
		DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)

		# Change our main viewport to output to the HMD
		get_viewport().use_xr = true
	else:
		print("OpenXR not initialized, please check if your headset is connected")

	# Deterministic results across runs
	seed(1337)


func _input(event):
	if event.is_action_pressed("fullscreen"):
		if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
		else:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)

func _process(_delta):
	# Follow hero
	# Works good enough for IARVR, but needs rework for bigger elevation changes.
	var pos = followedEntity.global_position
	pos.y = 0
	$XROrigin3D.global_position = pos
	# Causes motion sickness and disorientation.
	# However, user controlled camera rotation and translation might be neat.
	# $XROrigin3D.global_rotation = followedEntity.global_rotation

	# Control hero hands
	# Input is such that hand positions are relative to camera transform.
	# Project rotation to x-z plane
	# Is there a clever mathematical trick, which is faster and more beautiful?
	var v = $XROrigin3D/XRCamera3D.transform.basis * Vector3(0, 0, 1)
	var angle = atan2(v.x, v.z)
	var b = Basis().rotated(Vector3(0, 1, 0), angle).inverse()
	controlledEntity.moveHand(
		Puppet.HAND.LEFT,
		b * ($XROrigin3D/LeftPlayerHand.position - $XROrigin3D/XRCamera3D.position),
		b * $XROrigin3D/LeftPlayerHand.transform.basis)
	controlledEntity.moveHand(
		Puppet.HAND.RIGHT,
		b * ($XROrigin3D/RightPlayerHand.position - $XROrigin3D/XRCamera3D.position),
		b * $XROrigin3D/RightPlayerHand.transform.basis)
	controlledEntity.setGrab(Puppet.HAND.LEFT, $XROrigin3D/LeftPlayerHand.get_float("trigger") > 0.5)
	controlledEntity.setGrab(Puppet.HAND.RIGHT, $XROrigin3D/RightPlayerHand.get_float("trigger") > 0.5)