# CameraPivot.gd
# ─────────────────────────────────────────────────────────────────────────────
# Third-Person Kamerasystem – Kind-Node des Spielers
#
# Kamera-Modi:
#   • Kein Ziel, LMB gehalten  → Kamera orbitet um den Spieler (world_yaw ändert sich,
#                                  Spielerrotation bleibt)
#   • Kein Ziel, RMB gehalten  → Spieler + Kamera drehen sich gemeinsam
#   • Ziel markiert            → Soft Lock-On: Spieler dreht sich smooth zum Ziel,
#                                  Kamera bleibt direkt dahinter
#   • Mausrad                  → Zoom (min_zoom … max_zoom)
#
# world_yaw: absolute Weltausrichtung der Kamera in Grad (Y-Achse).
#   Unabhängig von player.rotation.y → verhindert Feedback-Loop bei Souls-Rotation.
#   camera_pivot.rotation.y wird in _process() immer als (world_yaw - player.rotation.y)
#   gesetzt, sodass die Kamera in World-Space stabil bleibt.
# ─────────────────────────────────────────────────────────────────────────────
extends Node3D

@export var sensitivity   = 0.3
@export var min_pitch     = -40.0
@export var max_pitch     = 20.0
@export var min_zoom      = 5.0
@export var max_zoom      = 20.0
@export var zoom_speed    = 1.0
@export var lock_on_speed = 5.0

var pitch: float = 0.0
var world_yaw: float = 0.0  # Absolute Weltausrichtung der Kamera (unabhängig von Spielerrotation)
var desired_zoom: float = 10.0  # Gewünschter Zoom-Abstand

@onready var camera = $Camera3D

func _ready():
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
	world_yaw = get_parent().rotation.y
	desired_zoom = camera.position.z

func _input(event):
	var player = get_parent()
	var has_target = player.target != null and is_instance_valid(player.target)

	if event is InputEventMouseMotion:
		if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
			# LMB: nur Kamera dreht sich, Spieler bleibt (auch mit Target → umschauen)
			world_yaw -= deg_to_rad(event.relative.x * sensitivity)
			pitch -= event.relative.y * sensitivity
			pitch = clamp(pitch, min_pitch, max_pitch)
			rotation_degrees.x = pitch
		elif Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT):
			# RMB: Spieler + Kamera drehen sich gemeinsam (auch mit Target → weglaufen)
			var delta_yaw = deg_to_rad(-event.relative.x * sensitivity)
			world_yaw += delta_yaw
			player.rotation.y += delta_yaw
			pitch -= event.relative.y * sensitivity
			pitch = clamp(pitch, min_pitch, max_pitch)
			rotation_degrees.x = pitch

	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
			desired_zoom = clamp(desired_zoom + zoom_speed, min_zoom, max_zoom)
		if event.button_index == MOUSE_BUTTON_WHEEL_UP:
			desired_zoom = clamp(desired_zoom - zoom_speed, min_zoom, max_zoom)

func _process(delta):
	var player = get_parent()

	var rmb_held = Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT)
	var lmb_held = Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT)
	if player.target != null and is_instance_valid(player.target) and not player.is_rolling and not rmb_held and not lmb_held:
		# Soft Lock-On: Spieler dreht sich zum Ziel, Kamera folgt direkt dahinter
		# (RMB gehalten → Lock-On pausiert, Spieler kann sich wegdrehen)
		var to_target = player.target.global_position - player.global_position
		to_target.y = 0
		if to_target.length() > 0.1:
			var target_angle = atan2(-to_target.x, -to_target.z)
			player.rotation.y = lerp_angle(player.rotation.y, target_angle, delta * lock_on_speed)
			world_yaw = player.rotation.y

	# Lokale Rotation so setzen dass Kamera immer auf world_yaw zeigt
	rotation.y = world_yaw - player.rotation.y

	# Kamera-Kollision: Raycast vom Pivot zur gewünschten Kameraposition
	var space_state = get_world_3d().direct_space_state
	var pivot_pos = global_position
	# Kamera sitzt auf lokaler Z-Achse des Pivots
	var desired_cam_local = Vector3(0, 0, desired_zoom)
	var desired_cam_pos = global_transform * desired_cam_local

	var query = PhysicsRayQueryParameters3D.create(pivot_pos, desired_cam_pos)
	query.exclude = [player.get_rid()]
	query.collide_with_bodies = true
	query.collide_with_areas = false
	query.collision_mask = 1
	var result = space_state.intersect_ray(query)

	if result and not result.collider is CharacterBody3D:
		var hit_dist = pivot_pos.distance_to(result.position) - 0.5
		camera.position.z = clamp(hit_dist, 1.0, desired_zoom)
	else:
		camera.position.z = lerp(camera.position.z, desired_zoom, delta * 5.0)
