class_name Player
extends CharacterBody2D

const SPEED: int = 1000

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var fight_animation: AnimatedSprite2D = $FightAnimation
@onready var cam: Camera2D = $Camera2D
@onready var raycast: RayCast2D = $RayCast2D
@onready var cursor_hide_timer: Timer = $CursorHideTimer
const RAYCAST_RANGE: int = 22

@export var tilemap: TileMapLayer
var tilesize: int = 32
var position_limit_rect: Rect2
const STILL_POSITIONS: Array[String] = ["sit_down", "sit_side", "hand_down", "hand_side", "hand_up"]

var health: int = 10
var damage: int = 2

func _ready() -> void:
	EventManager.player = self
	var used_tilemap_rect: Rect2i = tilemap.get_used_rect()
	tilesize = tilemap.tile_set.tile_size.x
	
	cam.limit_left = used_tilemap_rect.position.x * tilesize
	cam.limit_top = used_tilemap_rect.position.y * tilesize
	cam.limit_right = used_tilemap_rect.end.x * tilesize
	cam.limit_bottom = used_tilemap_rect.end.y * tilesize
	
	var margin: float = float(tilesize) / 4

	position_limit_rect = Rect2(
		Vector2(cam.limit_left + margin, cam.limit_top - margin),
		Vector2(
			(cam.limit_right - margin) - (cam.limit_left + margin),
			(cam.limit_bottom - margin / 2) - (cam.limit_top + margin / 2)
		)
	)

func _process(_delta: float) -> void:
	if EventManager.player_free && !EventManager.animation_player.is_playing() && Input.is_action_just_pressed("interact"):
		interact()

func interact() -> void:
	var interactable: Interactable
	if raycast.is_colliding() && raycast.get_collider() is Interactable:
		interactable = raycast.get_collider()
	else:
		interactable = null
	var fightable: Fightable
	if raycast.is_colliding() && raycast.get_collider() is Fightable:
		fightable = raycast.get_collider()
	else:
		fightable = null
		
	match animated_sprite.animation:
		"down":
			animated_sprite.play("hand_down")
			if interactable == null:
				fight_animation.rotation_degrees = 0
				fight_animation.play()
				$Hit.play()
				if !fight_animation.is_playing():
					fight_animation.play()
			await animated_sprite.animation_finished
			animated_sprite.animation = "down"
		"up":
			animated_sprite.play("hand_up")
			if interactable == null:
				fight_animation.rotation_degrees = 180
				fight_animation.play()
				$Hit.play()
				if !fight_animation.is_playing():
					fight_animation.play()
			await animated_sprite.animation_finished
			animated_sprite.animation = "up"
		"side":
			animated_sprite.play("hand_side")
			if interactable == null:
				$Hit.play()
				if animated_sprite.flip_h:
					fight_animation.rotation_degrees = 90
				else:
					fight_animation.rotation_degrees = -90
				if !fight_animation.is_playing():
					fight_animation.play()
			await animated_sprite.animation_finished
			animated_sprite.animation = "side"
	if interactable != null:
		interactable.interact(self)
	elif fightable != null:
		fightable.fight(self)

func _physics_process(delta: float) -> void:
	if !STILL_POSITIONS.has(animated_sprite.animation) && EventManager.player_free && !EventManager.animation_player.is_playing():
		var input := Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
		
		var raycast_input := Vector2.ZERO
		if abs(input.x) > abs(input.y):
			raycast_input.x = sign(input.x)
		elif abs(input.y) > 0:
			raycast_input.y = sign(input.y)
		if raycast_input != Vector2.ZERO:
			raycast.target_position = raycast_input * RAYCAST_RANGE
		
		velocity = input * delta * SPEED * 3
		
		move_and_slide()
		position = position.clamp(position_limit_rect.position, position_limit_rect.end)
	
		if velocity.length() != 0:
			animated_sprite.play()
			animated_sprite.flip_h = false
			if abs(velocity.x) > abs(velocity.y):
				animated_sprite.animation = "side"
				animated_sprite.flip_h = velocity.x < 0
			elif velocity.y < 0:
				animated_sprite.animation = "up"
			else:
				animated_sprite.animation = "down"
		else:
			animated_sprite.stop()

func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouse:
		cursor_hide_timer.stop()
		Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	elif EventManager.player_free && !EventManager.animation_player.is_playing() && !event.is_action("escape"):
		if cursor_hide_timer.is_stopped():
			cursor_hide_timer.start()
		await cursor_hide_timer.timeout
		Input.mouse_mode = Input.MOUSE_MODE_HIDDEN
