extends Node2D
const PhysicsFunc = preload("res://src/Utilities/Physic/PhysicsFunc.gd")

#Array of RayCast2D
onready var trigger_rays = $FlyingLaserCutterBody/Triggers.get_children()
onready var trigger_ray_textures = $FlyingLaserCutterBody/TriggerTextures.get_children()
onready var body = $FlyingLaserCutterBody
onready var local_facing: Vector2 = Vector2.RIGHT
onready var global_facing: Vector2 = local_facing.rotated(transform.get_rotation())
onready var slide_friction = 1.5

var flyoff_triggered = false
var has_hit_player = false
var halted = false
var returning = false
var initial_distance : float = 1.0

export(float) var velocity = 1
export(float) var max_velocity = 200
export(float) var acceleration_force = 1200
export(float) var mass = 10
export(bool) var avoid_crushing = false
export(bool) var fast_retrigger = false


func _ready() -> void:
	$FlyingLaserCutterBody/Sprite/AnimationPlayer.play("default")

func _process(delta: float) -> void:
	update_trigger_ray_shader()

func _physics_process(delta: float) -> void:
	
	if !flyoff_triggered:
		for ray in trigger_rays:
	
			# When player has been hit on the way
			if (has_hit_player && body.position.x > 0):
				break
	
			if ray.is_colliding() && (body.position.x < 1 || fast_retrigger):
				var collider = ray.get_collider()
				if collider.is_in_group("player"):
					flyoff_triggered = true
					body.set("motion/sync_to_physics", false)
					break
	
		if body.position.x > 0:
			if halted && avoid_crushing:
				return
			returning = true
			velocity=1
			body.position.x += (max_velocity/3)*-1*delta
	
		else:
			returning = false
			
	elif body.position.x == 0:
		has_hit_player = false
		
	if flyoff_triggered:
		returning = false
		velocity = PhysicsFunc.two_step_euler(
			velocity, acceleration_force, mass, delta
		)
		velocity = clamp(velocity, 0, max_velocity)
	
		var collision = body.move_and_collide(velocity*global_facing*delta,true)
	
		if collision != null:
			if !collision.collider.is_in_group("player"):
				body.set("motion/sync_to_physics", true)
			else:
				has_hit_player = true
			flyoff_triggered = false

func update_trigger_ray_shader() -> void:
	for i in trigger_rays.size():
		var raycast: RayCast2D = trigger_rays[i]
		var ray_texture: Sprite = trigger_ray_textures[i]
		var distance: float = (raycast.position + body.position).distance_to(to_local(raycast.get_collision_point()))
		ray_texture.material.set_shader_param("total_distance", distance)
		if initial_distance <= 1.0:
				initial_distance = distance
		if flyoff_triggered || returning:
			var factor : float = distance/initial_distance
			ray_texture.material.set_shader_param("wave1", 0)
			ray_texture.material.set_shader_param("wave2", 0)
			ray_texture.material.set_shader_param("wave3", 1)
			var constant_ray_color: Color = ray_texture.material.get_shader_param("wave3_color")
			constant_ray_color.a = 1.2 - 1.0 * factor
			ray_texture.material.set_shader_param("wave3_color", constant_ray_color)
		else:
			ray_texture.material.set_shader_param("wave1", 1)
			ray_texture.material.set_shader_param("wave2", 0)
			ray_texture.material.set_shader_param("wave3", 0)
			var constant_ray_color: Color = ray_texture.material.get_shader_param("wave3_color")
			constant_ray_color.a = 0.01
			ray_texture.material.set_shader_param("wave3_color", constant_ray_color)


func _on_BackArea_body_entered(body: Node) -> void:
	if(body.is_in_group("player")):
		halted = true


func _on_BackArea_body_exited(body: Node) -> void:
	if(body.is_in_group("player")):
		halted = false
