extends CharacterBody2D


const SPEED := 300.0
var health := 30.0 # represented in seconds
var newHealth := -1.0

@onready var bullet = preload("res://assets/scenes/playerBullet.tscn")
@onready var gun = $gun
@onready var gunSprite = $gun/sprite
@onready var animations = $AnimationPlayer
@onready var shootsfx = $shootsfx
@onready var hitsfx = $hitsfx
@onready var dashRect = $MeshInstance2D
@onready var poly = $Polygon2D

signal transitionStart(seconds)

var speedUp := 0.0
var speedScale := 2.0
var damageScale := 1.0
var minDamageScale := 1.0

var dashTimer := 0.0

var dashVel := Vector2.ZERO
var knockback := Vector2.ZERO

var flip := false
var ticks = 0
var tickToDel = 0

var frameData = {} # keep position, rotation and velocity for now

var amountTransition := 0.0
var transitioning := false
var transitionState = [false, false, false]
var targetState = []

var dead := false

var damage_stack := 1.0

var shotgun := 0

func heal(seconds):
	damage_stack *= pow(1.1, Globals.unlockedUpgrades.get("thoseWereTheDays", 0))
	
	newHealth = health + seconds
	transitionStart.emit(seconds)
	#print(frameData)
	targetState = frameData[max(tickToDel, ticks - (int(floor(seconds)) * 20))]
	transitioning = true
	
func healNoMove(seconds):
	newHealth = health + seconds

func _process(delta: float) -> void:
	if damageScale > minDamageScale: damageScale -= delta
	damageScale = max(damageScale, minDamageScale)
	
	shotgun = Globals.unlockedUpgrades.get("shotgun", 0)
	if shotgun > 0:
		gunSprite.region_rect = Rect2(64, 80, 32, 16)
	else:
		gunSprite.region_rect = Rect2(0, 112, 16, 16)
	#ticks += 1
	
	dashRect.position.y = 31 * dashTimer / Globals.DASH_WAIT / 2 - 31.0 / 2
	dashRect.scale.y = dashTimer / Globals.DASH_WAIT
	
	if health < 10:
		poly.position = Vector2(randi_range(-(10 - health) / 5,(10 - health) / 5), randi_range(-(10 - health) / 5,(10 - health) / 5))

	if health <= 0 and not dead:
		$explode.emitting = true
		$explode.unlock = true
		$explode.reparent(get_parent())
		$PointLight2D.reparent(get_parent())
		dead = true
		hide()


var grayscaleVal := 1.0

func _physics_process(delta: float) -> void:
	if dead: return
	
	if newHealth != -1:
		health += (newHealth - health) * 3 * delta
		
		if abs(health - newHealth) < 1:
			health = newHealth
			newHealth = -1

	if transitioning:
		
		grayscaleVal += - grayscaleVal * 10 * delta
		
		position += (targetState[0] - position) * 5 * delta / Engine.time_scale
		rotation += (targetState[1] - rotation) * 5 * delta / Engine.time_scale
		velocity += (targetState[2] - velocity) * 5 * delta / Engine.time_scale
		
		Engine.time_scale += (0.5 - Engine.time_scale) * 5 * delta / Engine.time_scale
		
		#
		#position = position.round()
		#rotation = round(rotation)
		#velocity = velocity.round()
		
		#print((position - targetState[0]).length(), " ", abs(rotation - targetState[1]), " ", (velocity - targetState[2]).length())
		
		if (position - targetState[0]).length() < 2:
			position = targetState[0]
			transitionState[0] = true
		if abs(rotation - targetState[1]) < 0.05:
			rotation = targetState[1]
			transitionState[1] = true
		if (velocity - targetState[2]).length() < 2:
			velocity = targetState[2]
			transitionState[2] = true
		
		if transitionState.count(true) == len(transitionState):
			transitioning = false
			transitionState = [false, false, false]
			targetState = []
			health = ceil(health)
			amountTransition = 0
		
		return

	grayscaleVal += (1-grayscaleVal) * 2 * delta

	var direction := Input.get_vector("moveLeft", "moveRight", "moveUp", "moveDown")
	velocity = direction * SPEED
	
	if Globals.unlockedUpgrades.get("fasterFaster", 0) > 0:
		velocity *= pow(1.15, Globals.unlockedUpgrades["fasterFaster"])
	
	gun.rotation += gun.get_angle_to(get_global_mouse_position()) * 7 * delta
	#print(fposmod(gun.rotation + PI, PI * 2) - PI)
	var truerot = fposmod(gun.rotation + PI, PI * 2) - PI
	if truerot < -PI / 2 or truerot > PI / 2:
		gun.scale.y += (-1 - gun.scale.y) * 10 * delta
		flip = true
	else:
		gun.scale.y += (1 - gun.scale.y) * 10 * delta
		flip = false
		
		
	var ang = gun.rotation + gun.get_angle_to(get_global_mouse_position())
	if Input.is_action_just_pressed("dash") and dashTimer == 0:
		dashVel = Vector2(cos(ang), sin(ang)) * Globals.DASH_LENGTH * pow(1.5, Globals.unlockedUpgrades.get("dashMachine", 0))
		dashTimer = Globals.DASH_WAIT * pow(0.8, Globals.unlockedUpgrades.get("dashMachine", 0))
		
	if dashTimer > 0: dashTimer -= delta
	else: dashTimer = 0
		
	if Input.is_action_just_pressed("shoot"):
		if not animations.is_playing():
			#var ang = gun.rotation + gun.get_angle_to(get_global_mouse_position())
			if shotgun > 0:
				for ind in range(-shotgun, shotgun + 1):
					var instantiated = bullet.instantiate()
					instantiated.global_position = global_position# + Vector2(cos(ang + ind * 0.2) * 16, sin(ang + ind * 0.3) * 16)
					instantiated.velocity.x = cos(ang + ind * 0.2) * 700
					instantiated.velocity.y = sin(ang + ind * 0.2) * 700
					get_parent().add_child(instantiated)
			else:
				var instantiated = bullet.instantiate()
				instantiated.global_position = global_position
				instantiated.velocity.x = cos(ang) * 700
				instantiated.velocity.y = sin(ang) * 700
				get_parent().add_child(instantiated)
			
			shootsfx.play()
		
		if flip: animations.play("shoot_flip")
		else: animations.play("shoot")
	
	#if Input.is_action_just_pressed("debugKey"):
		#targetState = frameData[ticks - 40]
		#transitioning = true
		
	if speedUp > 0:
		Engine.time_scale += (speedScale - Engine.time_scale) * delta / Engine.time_scale
		speedUp -= delta / speedScale
	else:
		speedScale = 1
		Engine.time_scale += (1 - Engine.time_scale) * 2 * delta / Engine.time_scale

	velocity += knockback
	velocity += dashVel
	knockback += -knockback * 5 * delta
	dashVel += -dashVel * 5 * delta

	move_and_slide()


func _on_framesave_timeout() -> void:
	frameData[ticks] = [position, rotation, velocity]
	ticks += 1
	
	if ticks > 240:
		frameData.erase(tickToDel)
		tickToDel += 1


func _on_hitbox_area_entered(area: Area2D) -> void:
	var themeta = area.get_meta("pickup", 0)
	#print("floyd")
	#
	if themeta != 0:
		area.get_node("particles").emitting = true
		area.get_node("particles").reparent(get_parent())
		healNoMove(3)
		area.queue_free()
		
		$"../hud/AnimationPlayer2".play("global/popItUp")

	if area.has_meta("kaboom"):
		speedScale = 2 * pow(0.8, Globals.unlockedUpgrades.get("rollback", 0))
		speedUp = 0.5
		damageScale += 2 * pow(0.8, Globals.unlockedUpgrades.get("rollback", 0))
		knockback = Vector2(sin(rotation) * 2000 * [0.5, -0.5].pick_random(), cos(rotation) * 2000 * [0.5, -0.5].pick_random())
