extends AbstractPrey2D

@onready var sprite = get_node("AnimatedSprite2D")
@onready var fsm = $StateMachine

var desired_rotation: float = self.rotation

# Mirrored sprites for periodic boundary
var mirrorSprite1: Node2D
var mirrorSprite2: Node2D
var mirrorSprite3: Node2D


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	health = maxHealth
	sprite.play("Healthy")
	
	mirrorSprite1 = sprite.duplicate()
	mirrorSprite2 = sprite.duplicate()
	mirrorSprite3 = sprite.duplicate()

	add_child(mirrorSprite1)
	add_child(mirrorSprite2)
	add_child(mirrorSprite3)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	# Boundary mirroring
	_handle_wrapping()

func _physics_process(delta: float) -> void:
	# rotate smoothly
	if self.rotation != self.desired_rotation: # FIXME: causes the mirror sprites to flip out
		self.rotation = lerp_angle(self.rotation, self.desired_rotation, 4 * delta)

func move(motion: Vector3) -> void:
	move_and_collide(Vector2(motion.x, motion.y))  # Moves along the given vector
	self.desired_rotation = atan2(motion.y, motion.x)	
		
	# Apply boundary to new position
	position = GameManager.get_boundaried_position(position)

func handle_damage(dmg: int, src: Node) -> void:
	health = max(0, health-dmg)
	if health == 0:
		die()
	if health < maxHealth:
		become_injured()
	fsm.transition_to_next_state(fsm.States.FLEEING, {"threat": src})
	
func die() -> void:
	sprite.play("Dying")
	super.die()

func become_injured() -> void:
	sprite.play("Injured")
	mirrorSprite1.play("Injured")
	mirrorSprite2.play("Injured")
	mirrorSprite3.play("Injured")

func _on_sight_body_entered(body: Node2D) -> void:
	if body.is_in_group("predators") or body.is_in_group("player"):
		fsm.transition_to_next_state(fsm.States.FLEEING, {"threat": body})

	
# Mirroring table:
# |---|---|---|---|
# | 4 | 3 | 4 | 3 |
# |---|===|===|---|
# | 1 ǁ 2 | 1 ǁ 2 |
# |---ǁ---|---ǁ---|
# | 4 ǁ 3 | 4 ǁ 3 |
# |---|===|===|---|
# | 1 | 2 | 1 | 2 |
# |---|---|---|---|
# If less than viewport size away from an edge, mirror over that edge (for seamless boundary)
# NOTE: For this to look correctly the camera size should be smaller than half the screen port (in
# 		any one dimension. Ideally, the difference between camera size and half the screen port is 
# 		at least the size of the prey sprite)
func _handle_wrapping():
	mirrorSprite1.visible = false
	mirrorSprite2.visible = false
	mirrorSprite3.visible = false
	
	# TODO: Assume viewport size << screen size and only draw according to GameManager.viewport_size
	# Find corresponding section of the screen
	if position.x < GameManager.screen_size.x/2 and position.y < GameManager.screen_size.y/2:
		# 2
		mirrorSprite1.visible = true
		mirrorSprite2.visible = true
		mirrorSprite3.visible = true
		
		# Right
		#mirrorSprite1.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y)
		mirrorSprite1.position = Vector2(GameManager.screen_size.x, 0)
		# Diag
		#mirrorSprite2.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y + GameManager.screen_size.y)
		mirrorSprite3.position = Vector2(GameManager.screen_size.x, GameManager.screen_size.y)
		# Bottom
		#mirrorSprite3.position = Vector2(sprite.position.x, sprite.position.y + GameManager.screen_size.y)
		mirrorSprite2.position = Vector2(0, GameManager.screen_size.y)

		
	elif position.x < GameManager.screen_size.x/2:
		# 3
		mirrorSprite1.visible = true
		mirrorSprite2.visible = true
		mirrorSprite3.visible = true
		
		# Top
		#mirrorSprite1.position = Vector2(sprite.position.x, sprite.position.y - GameManager.screen_size.y)
		mirrorSprite1.position = Vector2(0, - GameManager.screen_size.y)
		# Diag
		#mirrorSprite2.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y - GameManager.screen_size.y)
		mirrorSprite2.position = Vector2(GameManager.screen_size.x, - GameManager.screen_size.y)
		# Right
		#mirrorSprite3.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y)
		mirrorSprite3.position = Vector2(GameManager.screen_size.x, 0)
		
		
	elif position.y < GameManager.screen_size.y/2:
		# 1
		mirrorSprite1.visible = true
		mirrorSprite2.visible = true
		mirrorSprite3.visible = true
		
		# Left 
		#mirrorSprite1.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y)
		mirrorSprite1.position = Vector2(- GameManager.screen_size.x, 0)
		# Bottom
		#mirrorSprite2.position = Vector2(sprite.position.x, sprite.position.y + GameManager.screen_size.y)
		mirrorSprite2.position = Vector2(0, GameManager.screen_size.y)
		# Diag
		#mirrorSprite3.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y + GameManager.screen_size.y)
		mirrorSprite3.position = Vector2(- GameManager.screen_size.x, GameManager.screen_size.y)


	else:
		# 4
		mirrorSprite1.visible = true
		mirrorSprite2.visible = true
		mirrorSprite3.visible = true
		
		# Left
		#mirrorSprite1.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y)
		mirrorSprite1.position = Vector2(- GameManager.screen_size.x, 0)
		# Diag
		#mirrorSprite2.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y - GameManager.screen_size.y)
		mirrorSprite2.position = Vector2(- GameManager.screen_size.x, - GameManager.screen_size.y)
		# Top
		#mirrorSprite3.position = Vector2(sprite.position.x, sprite.position.y - GameManager.screen_size.y)
		mirrorSprite3.position = Vector2(0,  - GameManager.screen_size.y)
