extends CharacterBody3D
class_name Character

@export_group("Movement Settings")
@export var normal_speed: float = 6.0
@export var sprint_speed: float = 10.0
@export var jump_velocity: float = 10.0
@export var gravity_scale: float = 1.0
@export var rotation_speed: float = 10.0
@export var acceleration: float = 10.0  # Сила ускорения
@export var deceleration: float = 8.0   # Сила замедления

@export_group("References")
@export var body: Node3D = null
@export var spring_arm_offset: Node3D = null
@export var respawn_point: Vector3 = Vector3(0, 5, 0)

var _current_speed: float
var _target_velocity: Vector3 = Vector3.ZERO  # Целевая скорость
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var _has_input: bool = false
var _can_sprint: bool = true
	
func _ready():
	$SpringArmOffset/SpringArm3D/Camera3D.current = false
	
func _physics_process(delta):
	# Обработка гравитации
	if not is_on_floor():
		velocity.y -= gravity * delta
		_can_sprint = false  # В воздухе нельзя ускоряться
	else:
		_can_sprint = true  # На земле можно ускоряться
	
	# Обработка прыжка
	if is_on_floor() and Input.is_action_just_pressed("jump"):
		velocity.y = jump_velocity
		_can_sprint = false  # При прыжке сразу отключаем спринт
	
	_move(delta)
	move_and_slide()
	
	if body and body.has_method("animate"):
		body.animate(velocity)
	
func _process(_delta):
	_check_fall_and_respawn()
	
func _move(delta: float) -> void:
	var input_direction = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
	_has_input = input_direction.length() > 0.1
	
	# Получаем направление движения относительно камеры
	var camera_basis = $SpringArmOffset/SpringArm3D/Camera3D.global_transform.basis
	var direction = (camera_basis * Vector3(input_direction.x, 0, input_direction.y)).normalized()
	
	_update_speed()
	
	if direction:
		# Устанавливаем целевую скорость с учетом направления
		_target_velocity.x = direction.x * _current_speed
		_target_velocity.z = direction.z * _current_speed
		
		# Плавно изменяем скорость в сторону целевой
		velocity.x = lerp(velocity.x, _target_velocity.x, acceleration * delta)
		velocity.z = lerp(velocity.z, _target_velocity.z, acceleration * delta)
		
		# Поворачиваем тело персонажа в направлении движения
		if velocity.length() > 0.1:
			var target_rotation = atan2(_target_velocity.x, _target_velocity.z)
			body.rotation.y = lerp_angle(body.rotation.y, target_rotation, rotation_speed * delta)
	else:
		# Если нет ввода, плавно уменьшаем скорость
		_target_velocity = Vector3.ZERO
		velocity.x = lerp(velocity.x, 0.0, deceleration * delta)
		velocity.z = lerp(velocity.z, 0.0, deceleration * delta)
		
func is_running() -> bool:
	return Input.is_action_pressed("shift") and _current_speed == sprint_speed
	
func _update_speed() -> void:
	# Ускорение работает только когда персонаж на земле
	if _can_sprint and Input.is_action_pressed("shift"):
		_current_speed = sprint_speed
	else:
		_current_speed = normal_speed
		
func _check_fall_and_respawn():
	if global_transform.origin.y < -15.0:
		_respawn()
		
func _respawn():
	global_transform.origin = respawn_point
	velocity = Vector3.ZERO
	_target_velocity = Vector3.ZERO
	_can_sprint = true
