extends Node3D

@export_group("Speed")
@export var pan_speed: float = 5.0
@export var rotation_speed: float = 0.003

@export_group("Bounds")
@export var movement_bounds: AABB

@export_group("Ref")
@export var rotation_target: Node3D

@onready var camera: Camera3D = $%Camera3D

var total_yaw: float = 0.0  
var total_pitch: float = 0.0 
var orbit_distance: float = 0.0
var current_pan: Vector2 = Vector2.ZERO
var is_active: bool = false

func _ready() -> void:
	total_yaw = global_rotation.y
	total_pitch = global_rotation.x 
	
	if rotation_target:
		orbit_distance = global_position.distance_to(rotation_target.global_position)

func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed("toggle_photo_mode"):
		is_active = !is_active
		
		#get_tree().paused = is_active
		
		if !is_active:
			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
		else:
			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
		
	if event is InputEventMouseMotion and is_active:
		total_yaw -= event.relative.x * rotation_speed
	
	if event.is_action_pressed("take_photo"):
		take_photo_async()

func _process(delta: float) -> void:
	if not rotation_target:
		return
	
	
	var pan_input = Input.get_vector("photo_pan_left", "photo_pan_right", "photo_pan_up", "photo_pan_down")
	var rot_basis = Basis.from_euler(Vector3(total_pitch, total_yaw, 0))
	
	if pan_input != Vector2.ZERO and is_active:
		current_pan.x += pan_input.x * pan_speed * delta
		current_pan.y += -pan_input.y * pan_speed * delta
		
		if movement_bounds.size != Vector3.ZERO:
			current_pan.x = clampf(current_pan.x, movement_bounds.position.x, movement_bounds.position.x + movement_bounds.size.x)
			current_pan.y = clampf(current_pan.y, movement_bounds.position.y, movement_bounds.position.y + movement_bounds.size.y)
	
	var right_dir = rot_basis.x.normalized()
	var up_dir = rot_basis.y.normalized()
	
	var final_pan_offset = (right_dir * current_pan.x) + (up_dir * current_pan.y)
	
	var orbit_pos = rotation_target.global_position + (rot_basis * Vector3(0, 0, orbit_distance))
	
	global_position = orbit_pos + final_pan_offset
	global_basis = rot_basis

func take_photo_async() -> void:
	if !is_active:
		return
		
	var targets = get_tree().get_nodes_in_group("collectible")
	var space_state = get_world_3d().direct_space_state
	
	await CollectionManager.save_photo_to_disk_async()
	
	for target in targets:
		if not target.collectible_data:
			continue
			
		if camera.is_position_in_frustum(target.global_position):
			var query = PhysicsRayQueryParameters3D.create(camera.global_position, target.global_position)
			query.collide_with_areas = true 
			query.collide_with_bodies = true 
			
			var result = space_state.intersect_ray(query)
			
			if result and result.collider == target:
				CollectionManager.unlock_collectible(target.collectible_data.id)
	
	GameState.save_game()
