extends KinematicBody2D
export var swim_length   = 150
export var swim_cooldown = 1

var casual = false # True prevents restarting from beginning after dying
var destination # The position the fish will move to _on_SwimTimer_timeout()
var pellets_consumed = 0 # Tracks the number of clean pellets eaten
var invincible = false # Used during cutscenes such as returning home, etc
var poisoned = false # Used in Hazards/Poison/Poison.gd to determine if fish is dying of poison
var poison_mutating = false # Used in poison mutation cutscene
var poison_mutation = false # True when fish can eat and shoot poison pellets
var dash_mutation = false
var pellets = 0 # Tracks the number of poison pellets eaten but not shot yet
var do_not_rotate = false # Used in Fork.tscn cutscene to stop fish from auto-rotating
onready var mouth = $Positions/Mouth.position # Used for eating and shooting poison pellets
onready var mouth_inhale = $Positions/MouthInhale.position # Used for eating poison pellets
onready var tail = $Positions/Tail.position # Used for shooting poison pellets
onready var house = get_node("/root/Tank/House")
onready var house_eyes = get_node("/root/Tank/House/HouseEyes")
onready var house_left = get_node("/root/Tank/House/HouseLeft")
onready var house_right = get_node("/root/Tank/House/HouseRight")
onready var house_left_entrance = get_node("/root/Tank/House/LeftEntrance")
onready var house_right_entrance = get_node("/root/Tank/House/RightEntrance")


func _ready():
	$SwimTimer.wait_time = swim_cooldown
	$HungerTimer.start()


func _on_SwimTimer_timeout() -> void:
	# Swim toward mouse
	if not invincible:
		var new_y = clamp(move_toward(position.y, get_global_mouse_position().y, swim_length), 110, 1040)
		#destination = Vector2(move_toward(position.x, get_global_mouse_position().x, swim_length), move_toward(position.y, get_global_mouse_position().y, swim_length))
		destination = Vector2(move_toward(position.x, get_global_mouse_position().x, swim_length), new_y)
		$TweenSwim.interpolate_property(self, "position", position, destination, 1, Tween.TRANS_CUBIC, Tween.EASE_IN_OUT)
		$TweenSwim.start()
	else:
		if poison_mutating:
			destination.x = house_right_entrance.get_global_position().x
			destination.y = house_right_entrance.get_global_position().y + 100


func _process(delta: float) -> void:
	if destination and not do_not_rotate:
		var v
		if invincible: # Smoothly rotate fish to face destination
			v = destination - global_position
		else: # Smoothly rotate fish to face mouse
			v = get_global_mouse_position() - global_position
		var angle = v.angle() + deg2rad(270)
#		if global_position.x < get_global_mouse_position().x:
#			$AnimatedSprite.flip_v = false
#		else:
#			$AnimatedSprite.flip_v = true
		if rad2deg(angle) < 180 or rad2deg(angle) > 360:
			$AnimatedSprite.flip_v = true
		else:
			$AnimatedSprite.flip_v = false
		var rotation_speed = PI * 0.75 # PI = 180 degrees
		var angle_delta = rotation_speed * delta
		angle = lerp_angle(global_rotation, angle + 1.57, 1.0)
		angle = clamp(angle, global_rotation - angle_delta, global_rotation + angle_delta)
		global_rotation = angle
		$ThoughtBubble.global_rotation = 0


func fire_pellet() -> void:
	var velocity = 4
	#pellets = 1 # This is just hax so we don't have to eat pellets first to fire them
	if pellets > 0: # But usually we require fish to eat pellets before he shoots them
		var poison_scene = load("res://Hazards/Poison/Poison.tscn")
		var poison = poison_scene.instance()
		poison.projectile = true # This will prevent the fish from auto-eating it the second it spawns
		get_parent().add_child(poison) # We add this projectile to the /tank/ so they don't move with the fish
		poison.position = $Positions/Tail.get_global_position() # 'position' returns the local position, but we need where it's at in relation to the tank
		poison.apply_central_impulse(velocity * ($Positions/Tail.get_global_position() - $Positions/Mouth.get_global_position()))
		pellets -= 1


func dash() -> void:
	$SwimTimer.stop()
	if invincible and get_parent().phase == get_parent().Phase.KNIFE and get_node_or_null("/root/Tank/Fork"):
		get_node("/root/Tank/FishFork").visible = false
		destination = Vector2(position.x - (swim_length*3.5), position.y)
		invincible = false
		if get_node_or_null("/root/Tank/Fork"):
			get_node("/root/Tank/Fork").retract()
		get_parent().get_node("SurviveTimer").start()
		do_not_rotate = false
	else:
		var new_y = clamp(move_toward(position.y, get_global_mouse_position().y, swim_length*3), 110, 1040)
		destination = Vector2(move_toward(position.x, get_global_mouse_position().x, swim_length*3), new_y)
	$TweenSwim.interpolate_property(self, "position", position, destination, 1, Tween.TRANS_CUBIC, Tween.EASE_IN_OUT)
	$TweenSwim.start()
	$SwimTimer.start()


func go_inside() -> void:
	invincible = true
	destination = house_left_entrance.get_global_position()
	$TweenSwim.stop_all()
	$TweenHome.interpolate_property(self, "position", position, destination, 1.5, Tween.TRANS_SINE, Tween.EASE_OUT, 1.5)
	$TweenHome.start()
	yield($TweenHome, "tween_completed")
	house_right.z_index = 1
	destination = house_right_entrance.get_global_position()
	$TweenInside.interpolate_property(self, "position", position, destination, 1.5, Tween.TRANS_SINE, Tween.EASE_OUT)
	$TweenInside.start()
	yield($TweenInside, "tween_completed")
	visible = false
	house_eyes.visible = true
	$TweenSleep.interpolate_property(get_parent(), "modulate", get_parent().modulate, Color(0,0,0,1), 2, Tween.TRANS_LINEAR, Tween.EASE_IN)
	$TweenSleep.start()
	yield($TweenSleep, "tween_completed")


func reset_hunger() -> void:
	if get_parent().phase == get_parent().Phase.CLEAN:
		$HungerTimer.start()
		pellets_consumed += 1
		if pellets_consumed > 5:
			get_parent().blackout()


func belly_up(_cause: String) -> void:
	print("You died on account of " + _cause + ". :(")
	# flip fish upside-down
	# modulate tank red
	if not casual:
		get_parent().phase = get_parent().Phase.START
	get_tree().reload_current_scene()


func _on_HungerTimer_timeout() -> void:
	if get_parent().phase == get_parent().Phase.CLEAN:
		belly_up("starvation")
	else:
		$HungerTimer.stop()


func _on_ThoughtTimer_timeout() -> void:
	$ThoughtBubble.visible = false
