class_name EntityMovement extends Node

const GRAVITY = Vector3.DOWN * 100
const FRICTION = 0.01
const WALK_SPEED_DEFAULT = 8
const RUN_SPEED_DEFAULT = 12

# var _inputDir:Vector2 = Vector2.ZERO
# var _running:bool = false

@export var entity:Entity
@export var interactingArea:EntityInteractingArea
# @export var rotate:Node3D
@export var walkSpeed:float = WALK_SPEED_DEFAULT
# @export var runSpeed:float = RUN_SPEED_DEFAULT

#
# Private Methods
#
func _applyGravity() -> void:
  if !entity.is_on_floor():
    entity.velocity += GRAVITY * get_process_delta_time()

func _applyPlayerMovement(_delta:float):
  # Interactions, may move
  if Input.is_action_just_pressed("interact") && interactingArea && interactingArea.hasInteraction():
    interactingArea.interact()
    return

  # Directional input
  var inputDir:Vector2 = Input.get_vector("move_left", "move_right", "move_back", "move_forward").normalized()
  var cameraCurrent = get_viewport().get_camera_3d()
  if !cameraCurrent:
    return

  # Use camera orientation for movement direction
  var camBasis = cameraCurrent.global_transform.basis

  # Forward and right vectors, ignore vertical component
  var forward = -camBasis.z
  forward.y = 0
  forward = forward.normalized()
  var right = camBasis.x
  right.y = 0
  right = right.normalized()

  var directionAdjusted = (forward * inputDir.y + right * inputDir.x).normalized()
  if directionAdjusted.length() <= 0.01:
    return

  entity.look_at(entity.global_position + directionAdjusted, Vector3.UP)

  var speed = walkSpeed
  entity.velocity.x = directionAdjusted.x * speed
  entity.velocity.z = directionAdjusted.z * speed

func _applyMovement(delta:float) -> void:
  if !_canMove():
    return

  if entity.movementType == Entity.MovementType.PLAYER:
    _applyPlayerMovement(delta)

func _applyFriction(delta:float) -> void:
  entity.velocity.x *= delta * FRICTION
  entity.velocity.z *= delta * FRICTION

func _canMove() -> bool:
  if UI.dialogueActive:
    return false
  if !UI.TEXTBOX.isClosed:
    return false
  if UI.GAME_MENU && UI.GAME_MENU.isOpen():
    return false
  return true

#
# Callbacks
#
func _enter_tree() -> void:
  pass

func _physics_process(delta:float) -> void:
  # Entity required to move
  if !entity || entity.movementType == Entity.MovementType.DISABLED || !entity.visible:
    return
  
  _applyGravity()
  _applyFriction(delta)
  _applyMovement(delta)
  entity.move_and_slide()
