class_name PlayerMovement
extends RefCounted

@export var _move_speed: float = 8
@export var _move_acceleration: float = 100
@export var _move_deceleration: float = 50

@export var _fall_speed: float = 20
@export var _fall_acceleration: float = 25

var move_input: Vector2

var _move_direction: Vector3

var _move_left: float
var _move_right: float
var _move_up: float
var _move_down: float


func handle_input(event: InputEvent, mode: Inputer.Mode) -> void:
	if mode == Inputer.Mode.KB_MOUSE:
		if event is not InputEventKey:
			return
		var key_event := event as InputEventKey
		if key_event.is_action_pressed("move_left"):
			_move_left = 1
		elif key_event.is_action_released("move_left"):
			_move_left = 0
		if key_event.is_action_pressed("move_right"):
			_move_right = 1
		elif key_event.is_action_released("move_right"):
			_move_right = 0
		if key_event.is_action_pressed("move_up"):
			_move_up = 1
		elif key_event.is_action_released("move_up"):
			_move_up = 0
		if key_event.is_action_pressed("move_down"):
			_move_down = 1
		elif key_event.is_action_released("move_down"):
			_move_down = 0

	if mode == Inputer.Mode.CONTROLLER:
		_move_left = Input.get_action_raw_strength("move_left")
		_move_right = Input.get_action_raw_strength("move_right")
		_move_up = Input.get_action_raw_strength("move_up")
		_move_down = Input.get_action_raw_strength("move_down")


func movement(
	velocity: Vector3, delta: float, is_on_floor: bool, can_move: bool
) -> Vector3:
	velocity = _lateral_movement(velocity, delta, can_move)
	velocity = _vertical_movement(velocity, delta, is_on_floor)

	return velocity


func _lateral_movement(velocity: Vector3, delta: float, can_move: bool) -> Vector3:
	if Referencer.players_count == 1:
		move_input = Input.get_vector("move_left", "move_right", "move_up", "move_down")
	else:
		move_input = _get_vector_from_raw_strengths(
			_move_left, _move_right, _move_up, _move_down
		)
	Debugger.text("move_input" + str(get_instance_id()), move_input)

	if move_input.length() > 0 and can_move:
		_move_direction = Vector3(move_input.x, 0, move_input.y).normalized().rotated(
			Vector3.UP, Referencer.main_camera.rotation.y
		)
		var new_velocity := _move_direction * _move_speed
		new_velocity.y = velocity.y
		velocity = velocity.move_toward(new_velocity, _move_acceleration * delta)
	else:
		var new_velocity := Vector3.ZERO
		new_velocity.y = velocity.y
		velocity = velocity.move_toward(new_velocity, _move_deceleration * delta)

	return velocity


func _vertical_movement(velocity: Vector3, delta: float, is_on_floor: bool) -> Vector3:
	if not is_on_floor:
		var new_velocity := velocity
		new_velocity.y = -_fall_speed
		velocity = velocity.move_toward(new_velocity, _fall_acceleration * delta)
	else:
		velocity.y = 0

	return velocity


func _get_vector_from_raw_strengths(
	negative_x: float,
	positive_x: float,
	negative_y: float,
	positive_y: float,
	deadzone := 0.5
) -> Vector2:
	var vector := Vector2(positive_x - negative_x, positive_y - negative_y)

	var length := vector.length()

	if length <= deadzone:
		return Vector2.ZERO
	if length > 1.0:
		return vector.normalized()

	return vector * inverse_lerp(deadzone, 1.0, length) / length
