extends CharacterBody3D

@export var mouse_sensitivity = 1

# ======== Movement Stuff


const walk_speed = 10.0
var crouch_speed = 5
var slide_speed = 25
var slide_friction = 5
var slide_direction = Vector3.ZERO
const jump_velocity = 4.5


# ========= Cam Stuff
var max_look_up = deg_to_rad(80)
var max_look_down = deg_to_rad(-80)
var crouch_height = 0.6 
var stand_height = 1.0
var pitch = 0

@onready var camera_pivot = $CameraPivot

# ========= Other Stuff
var is_crouching = false
var is_sliding = false

func _ready() -> void:
	mouse_sensitivity = mouse_sensitivity * 0.001
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	
	
	
func _input(event: InputEvent) -> void:
	if event.is_action_pressed("ui_cancel"):
		Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
	if event is InputEventMouseButton:
		Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	


func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouseMotion:
		rotate_y(-event.relative.x * mouse_sensitivity)
		
		pitch -= event.relative.y * mouse_sensitivity
		pitch = clamp(pitch, max_look_down, max_look_up)
		camera_pivot.rotation.x = pitch

func _physics_process(delta: float) -> void:
	
	var target_height = crouch_height if is_crouching else stand_height
	camera_pivot.position.y = lerp(camera_pivot.position.y, target_height, 10 * delta)



	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = jump_velocity

	var input_dir = Vector3.ZERO
	if Input.is_action_pressed("move_forward"):
		input_dir -= transform.basis.z
	if Input.is_action_pressed("move_backward"):
		input_dir += transform.basis.z
	if Input.is_action_pressed("move_left"):
		input_dir -= transform.basis.x
	if Input.is_action_pressed("move_right"):
		input_dir += transform.basis.x
	input_dir = input_dir.normalized()

	handle_crouch(input_dir, delta)


	move_and_slide()
	
	
func handle_crouch(input_dir:Vector3, delta):
	if Input.is_action_just_pressed("crouch") and is_on_floor():
		is_crouching = true
		
		if input_dir.length() > 0.1:
			start_slide(input_dir)
	
	if Input.is_action_just_released("crouch"):
		stop_crouch()



	if is_sliding:
		velocity.x = slide_direction.x
		velocity.z = slide_direction.z
		
		slide_direction = slide_direction.move_toward(Vector3.ZERO, slide_friction * delta)
		
		if slide_direction.length() < 1:
			is_sliding= false
			
	elif is_crouching:
		velocity.x = input_dir.x * crouch_speed
		velocity.z = input_dir.z * crouch_speed
	else:
		velocity.x = input_dir.x * walk_speed
		velocity.z = input_dir.z * walk_speed

func start_slide(input_dir: Vector3):
	is_sliding = true
	slide_direction = input_dir*slide_speed
	
func stop_crouch():
	is_crouching = false
	is_sliding = false
