extends CharacterBody2D

const speed = 100 
const dodge_speed = 200  # Speed during dodge
const dodge_duration = 0.5  # How long the dodge lasts (in seconds)
const dodge_cooldown_time = 3.0  # Dodge cooldown (in seconds)

var current_direction = "none"
var is_dodging = false
var dodge_cooldown_active = false

var enemy_in_attack_range = false
var enemy_attack_cooldown = true
var healt = 100 # return to 100 before turnin
var player_alive = true
var attack_ip = false

var attack_in_progress = false  # New state for attack-in-progress

# variables for game progress
var has_blue_potion = false
var has_red_potion = false
var has_green_potion = false
var coin_count = 0

var word_chunks = []  # Stores the words to show in chunks
var current_chunk_index = 0  # Tracks which chunk we're on

# Call this to start displaying the text in chunks
func show_text_in_chunks(full_text: String) -> void:
	# Add wizard/knight-style ending at the end
	full_text += " Ave Domine Limosus, gloria regni slime aeterni!"

	# Tokenize the full text into words and punctuation
	word_chunks = tokenize_text(full_text)
	current_chunk_index = 0
	$"TextEdit".visible = true
	$"TextEdit".text = ""  # Start clean

	set_process(true)  # Allow input checking in _process

# Tokenize text into words and punctuation marks separately
func tokenize_text(text: String) -> Array:
	var regex = RegEx.new()
	regex.compile(r"[\w']+|[.,!?;]")  # Match words and punctuation
	var matches = regex.search_all(text)
	var tokens = []
	for match in matches:
		tokens.append(match.strings[0])
	return tokens

# Called every frame, listens for just-pressed input to show next chunk
func _process(_delta):
	if Input.is_action_just_pressed("ui_accept"):
		if current_chunk_index * 7 < word_chunks.size():
			_display_next_chunk()
		elif $"TextEdit".visible:
			_display_empty_chunk()

# Show the current chunk of exactly 7 words
func _display_next_chunk() -> void:
	var start = current_chunk_index * 7
	var end = min(start + 7, word_chunks.size())
	var chunk_text = " ".join(word_chunks.slice(start, end))
	$"TextEdit".text = chunk_text
	current_chunk_index += 1

# Show empty chunk and hide the box
func _display_empty_chunk() -> void:
	$"TextEdit".text = ""
	$"TextEdit".visible = false
	set_process(false)



func resetGame():
	has_blue_potion = false
	has_red_potion = false
	has_green_potion = false
	current_direction = "none"
	is_dodging = false
	dodge_cooldown_active = false
	enemy_in_attack_range = false
	enemy_attack_cooldown = true
	healt = 100
	player_alive = true
	attack_ip = false
	position.x = 0
	position.y = 0
	
	
func _ready():
	var animation = $AnimatedSprite2D
	animation.play("front_idle")

	# Initialize dodge cooldown bar at full value
	$DodgeCoolDownBar.max_value = dodge_cooldown_time
	$DodgeCoolDownBar.value = dodge_cooldown_time  # Start at full

	# Make sure healthbar is always visible
	$healthbar.visible = true  # Set to true to always display health bar

func _physics_process(delta):
	player_movement()
	enemy_attack()
	play_attack_animation()
	update_healt()
	update_dodge_cooldown(delta)

	if healt <= 0:
		player_alive = false
		healt = 0
		print("Player has been killed")
		resetGame()

func player_movement():
	velocity = Vector2.ZERO
	
	if Input.is_action_pressed("ui_right"):
		velocity.x = speed
		current_direction = "right"
		
	if Input.is_action_pressed("ui_left"):
		velocity.x = -speed
		current_direction = "left"
	
	if Input.is_action_pressed("ui_down"):
		velocity.y = speed
		current_direction = "down"
	
	if Input.is_action_pressed("ui_up"):
		velocity.y = -speed
		current_direction = "up"

	# Normalize velocity for diagonal movement
	if velocity.length() > speed:
		velocity = velocity.normalized() * speed

	if is_dodging:
		velocity = velocity.normalized() * dodge_speed  # Apply dodge boost
	
	# Use move_and_slide() with only the velocity
	move_and_slide()

	# Play walking or idle animation
	if velocity != Vector2.ZERO and !attack_in_progress:
		play_animation(1)  # Walking animation
	elif !attack_in_progress:
		play_animation(0)  # Idle animation

func play_animation(movement):
	var dir = current_direction
	var animation = $AnimatedSprite2D
	
	if dir == "right":
		animation.flip_h = false
		if movement == 1:
			animation.play("side_walk")
		elif movement == 0:
			if !attack_ip:
				animation.play("side_idle")
	if dir == "left":
		animation.flip_h = true
		if movement == 1:
			animation.play("side_walk")
		elif movement == 0:
			if !attack_ip:
				animation.play("side_idle")
	if dir == "down":
		animation.flip_h = false
		if movement == 1:
			animation.play("front_walk")
		elif movement == 0:
			if !attack_ip:
				animation.play("front_idle")
	if dir == "up":
		animation.flip_h = false
		if movement == 1:
			animation.play("back_walk")
		elif movement == 0:
			if !attack_ip:
				animation.play("back_idle")

func play_attack_animation():
	var dir = current_direction
	var animation = $AnimatedSprite2D
	var timer = $deal_attack_timer
	
	if Input.is_action_just_pressed("attack") and !attack_in_progress:
		attack_in_progress = true
		global.player_current_attack = true
		attack_ip = true
		if dir == "right":
			animation.flip_h = false
			animation.play("side_attack")
			timer.start()
		elif dir == "left":
			animation.flip_h = true
			animation.play("side_attack")
			timer.start()
		elif dir == "down":
			animation.flip_h = false
			animation.play("front_attack")
			timer.start()
		elif dir == "up":
			animation.flip_h = false
			animation.play("back_attack")
			timer.start()

func _on_deal_attack_timer_timeout():
	var timer = $deal_attack_timer
	timer.stop()
	global.player_current_attack = false
	attack_ip = false
	attack_in_progress = false  # Reset attack progress

func _on_player_hitbox_body_entered(body):
	if body.has_method("enemy"):
		enemy_in_attack_range = true

func _on_player_hitbox_body_exited(body):
	if body.has_method("enemy"):
		enemy_in_attack_range = false

func player():
	pass

func enemy_attack():
	if enemy_in_attack_range && enemy_attack_cooldown:
		healt -= 10
		enemy_attack_cooldown = false
		$attack_cooldown.start()
		print("Current healt: ", healt)

func _on_attack_cooldown_timeout():
	enemy_attack_cooldown = true

func update_healt():
	var healtbar = $healthbar
	healtbar.value = healt
	# Healthbar is now always visible
	if healt >= 100:
		healtbar.visible = true  # Ensure it's visible at all times
	else:
		healtbar.visible = true  # Ensure it's visible even when health drops below 100

func _on_regen_timer_timeout():
	if healt < 100:
		healt = healt + 20
		if healt > 100:
			healt = 100
	if healt <= 0:
		healt = 0

# Handle Dodge
func _input(event):
	if event.is_action_pressed("dodge") and !dodge_cooldown_active:
		is_dodging = true
		# When dodge is triggered, set the cooldown to 0 (start cooldown)
		$DodgeCoolDownBar.value = 0
		# Dodge lasts for a short time
		await get_tree().create_timer(dodge_duration).timeout
		is_dodging = false
		dodge_cooldown_active = true

# Update Dodge cooldown
func update_dodge_cooldown(delta):
	if dodge_cooldown_active:
		$DodgeCoolDownBar.value += delta  # Slowly fill up the dodge bar over time
		if $DodgeCoolDownBar.value >= dodge_cooldown_time:
			dodge_cooldown_active = false
			$DodgeCoolDownBar.value = dodge_cooldown_time  # Reset to full after cooldown ends


func gameEnd() -> void:
	while $"TextEdit".visible:
		await get_tree().create_timer(1.0).timeout
	print("The game has been beaten!")
	queue_free()
	get_tree().quit()
		


func enterHouseNico(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(1290, 1130)
		

func leaveHouseNico(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(1300, 580)


func goIntoBasementNico(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(1100, 1130)


func leaveBasementNico(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(1250, 1200)


func enterHouse(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(400, -800)


func leaveHouse(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(80, -30)


func enterCastle(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(3820, -1025)


func leaveCastle(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(2420, -1225)


func layer0(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(3620, -1425)


func layer1(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(4220, -1025)


func layer2(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(4820, -1025)


func layer3(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(4220, -1325)


func layer4(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(4820, -1325)


func layer5(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(5420, -1325)


func layer6(body: Node2D) -> void:
	if body == self:
		self.position = Vector2(5420, -1025)


func leaveDungeon(body: Node2D) -> void:
	if body == self:
		enterCastle(self)



func keyPickUp(body: Node2D) -> void:
	if body == self:
		$"../collectables/Area2D".queue_free()
		$"../center-left/StaticBody2D".queue_free()



func pickUpRedPotion(body: Node2D) -> void:
	if body == self:
		$"../collectables/Area2D2".queue_free()
		has_red_potion = true


func pickUpBluePotion(body: Node2D) -> void:
	if body == self:
		$"../collectables/Area2D3".queue_free()
		has_blue_potion = true


func pickUpGreenPotion(body: Node2D) -> void:
	if body == self:
		$"../collectables/Area2D4".queue_free()
		has_green_potion = true


func pickUpCoin1(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin1".queue_free()
		coin_count +=1
		print(coin_count)

func pickUpCoin2(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin2".queue_free()
		coin_count +=1
		print(coin_count)


func pickUpCoin3(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin3".queue_free()
		coin_count +=1
		print(coin_count)


func pickUpCoin4(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin4".queue_free()
		coin_count +=1
		print(coin_count)


func pickUpCoin5(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin5".queue_free()
		coin_count +=1
		print(coin_count)


func pickUpCoin6(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin6".queue_free()
		coin_count +=1
		print(coin_count)


func pickUpCoin7(body: Node2D) -> void:
	if body == self:
		$"../collectables/coins/coin7".queue_free()
		coin_count += 1
		print(coin_count)


func wizardTalking(body: Node2D) -> void:
	if body == self:
		if has_blue_potion and has_green_potion and has_red_potion:
			show_text_in_chunks(
				"By the stars, you actually did it! You brought all three potions—red, green, and blue!

				...Oh. Uh, yeah—about that. So here's the thing...
				You only need to drink the red one to return to your world. The other two?
				Yeah those were... kinda for me. I just really like how the green one tastes with toast. And the blue one? Makes bath time way more interesting. Heh.

				Anyway! Bottoms up with that red one, and—poof!—you’re home.

				No refunds!"
			)
			
			gameEnd()
		else:
			show_text_in_chunks("Ah... you're not from this world, are you? Curious. Your aura—it's foreign, like a breeze from a land long forgotten. Fear not! I can send you back... but the spell requires three ancient potions: red, green, and blue. They're scattered deep within this slime-infested forest. Charming place, really. Oh, before you go stumbling into a slime's belly, a few pointers: WASD or arrow keys to move, Spacebar for a quick dodge—handy for avoiding gooey hugs, and to deal with trouble, just left-click or press E to strike. Now go! The forest won’t wait... and neither will the slimes.")


func knightTalking(body: Node2D) -> void:
	if body == self and coin_count >= 6:
		show_text_in_chunks(
			"...Well now. You actually returned... and with all seven coins of Lazaret, no less.

			Many have entered that cursed dungeon—most were not so fortunate.

			You’ve proven your strength... and your spirit. As promised, I shall open the gate.

			The blue potion is yours. Use it wisely—it holds power not meant for the faint of heart.

			May your path forward be clear... and your enemies less so."
		)

		$"../north/StaticBody2D2".queue_free()
		coin_count = 0
	elif body == self:
		show_text_in_chunks(
			"Ah, I see your eyes are fixed on that glowing prize beyond the gate—the blue potion. So close you could almost taste it… yet still out of reach.

			Know this: that potion is not yours for the taking—not yet. Only those who prove their worth may claim it.

			Venture into the dungeon below and retrieve the Sixa Gold Coins of Lazaret. Only then will I raise this gate.

			Do not return empty-handed... or not at all."
		)
		
	
