extends CharacterBody3D

class_name Player

enum PLAYER_STATUS {NOT_READY, WALKING, TALKING}

signal score_increased

@export var movement_speed = 320

var player_number = 1

var status : PLAYER_STATUS = PLAYER_STATUS.NOT_READY

@onready var animation_player1 = $mesh_owner/player1mesh/AnimationPlayer
@onready var animation_player2 = $mesh_owner/player2mesh/AnimationPlayer

var my_animator

var movement_velocity: Vector3
var rotation_direction: float
var gravity = 0

var nearest_npc = null
var score = 0
var score_multiplier = 1
var doing_something = false

func _ready():
	pass

func setup(number, position):
	player_number = number
	global_position = position
	if (number == 1):
		$mesh_owner/player2mesh.visible = false
		my_animator = animation_player1
	else:
		$mesh_owner/player1mesh.visible = false
		my_animator = animation_player2
		
	interact_ui_visible(false)
	%Interact.visible = false
	
	my_animator.play("Walk")

func _physics_process(delta):
	if (status == PLAYER_STATUS.NOT_READY):
		return

	handle_movement(delta)
	handle_gravity(delta)

	var applied_velocity: Vector3
	
	applied_velocity = velocity.lerp(movement_velocity, delta * 10)
	applied_velocity.y = -gravity

	velocity = applied_velocity
	move_and_slide()


func _process(delta):
	if (status == PLAYER_STATUS.NOT_READY):
		return

	handle_interaction()

func handle_movement(delta):
	var input := Vector3.ZERO
	
	if (status == PLAYER_STATUS.WALKING):
		if (player_number == 1):
			input.x = Input.get_axis("move_left1", "move_right1")
			input.z = Input.get_axis("move_forward1", "move_back1")
		else:
			input.x = Input.get_axis("move_left2", "move_right2")
			input.z = Input.get_axis("move_forward2", "move_back2")

	input = input.normalized()

	velocity = input * movement_speed * delta
	
	var dir = input.normalized()
	dir.y = position.y - 0.1
	$mesh_owner.look_at(position - dir, Vector3.UP)
	

func handle_interaction():
	if (nearest_npc == null):
		return

	if (status == PLAYER_STATUS.WALKING):
		if (Input.is_action_just_pressed("interact")):
			talk_to_nearest_npc()

	if (doing_something):
		return
	
	if (status == PLAYER_STATUS.TALKING):
		if (Input.is_action_just_pressed("tell_joke")):
			my_animator.play("Joke")
			do_something(1)

		if (Input.is_action_just_pressed("funny")):
			my_animator.play("Funny")
			do_something(2)

		if (Input.is_action_just_pressed("cheer")):
			my_animator.play("Cheer")
			do_something(3)

func _unhandled_input(event):
	pass

func handle_gravity(delta):
	gravity += 25 * delta
	
	if gravity > 0 and is_on_floor():
		gravity = 0


func _on_area_3d_body_entered(body):
	if (body is NPC):
		if (body.status == NPC.NPC_STATUS.WALKING and status == PLAYER_STATUS.WALKING):
			nearest_npc = body
			%Interact.visible = true


func _on_area_3d_body_exited(body):
	if (nearest_npc == body):
		nearest_npc = null
		%Interact.visible = false

func talk_to_nearest_npc():
	status = PLAYER_STATUS.TALKING
	nearest_npc.talk_to(self)
	interact_ui_visible(true)
	my_animator.play("Talking")
	%Interact.visible = false

func npc_made_happy(score_to_add):
	score += score_to_add
	status = PLAYER_STATUS.WALKING
	score_increased.emit(player_number, score)
	interact_ui_visible(false)
	nearest_npc = null
	my_animator.play("Walk")


func interact_ui_visible(is_visible : bool):
	%DoAFunny.visible = is_visible
	%TellAJoke.visible = is_visible
	%Cheer.visible = is_visible


func do_something(what : int):
	interact_ui_visible(false)
	doing_something = true
	await get_tree().create_timer(1.5).timeout
	interact_ui_visible(true)
	doing_something = false
	if (nearest_npc):
		nearest_npc.player_did_something(what)
