extends Node2D

onready var blobby = get_node("%Blobby")

var last_distance: Vector2 = Vector2(100,100)

# TODO Incorporate other enteties and highlight mass differences
var time := 0.0
var radius = 15
export var v_radius = 15
export var draft_radius = 20
export var interact_power = 0.04
export var max_displacement = 7
export var fps_limit := 30
var rand = rand_range(1,1.3)
var displacement_coeff: Vector2 = Vector2(1.0,0)
var saved_displacement
var is_idle_swinging
var start_swing_time := 0.0
var begin_idle
var time_since_last_exec := 0.0

var grass_sounds := ["res://assets/sounds/grass swish 1.ogg","res://assets/sounds/grass swish 2.ogg",
"res://assets/sounds/grass swish 3.ogg","res://assets/sounds/grass swish 4.ogg"]
# var thread : Thread

var saved_coeff:= 0.0

func _ready():
	# TODO This could probably fuck something up later? For other randomness based events
	randomize()
	# thread = Thread.new()


func _process(delta: float) -> void:
	# TODO This should be in the settings and applied to all shaders
	time_since_last_exec += delta
	# if thread.is_alive():
	# 	print("was_running")
	# 	return
	# if thread.is_active():
	# 	thread.wait_to_finish()
	if time_since_last_exec <= 1.0/fps_limit:
		return
	# thread.start(self, "grass_wave_update", delta)
	grass_wave_update(delta)


func grass_wave_update(delta: float) -> void:
	time_since_last_exec = 0.0
	var distance: float = abs(global_position.x - blobby.global_position.x + 6)
	var v_distance: float = abs(global_position.y - blobby.global_position.y + 11)
	#if (distance > draft_radius * 2 || v_distance > v_radius * 2):
	#    return
	#Velocity relative to the grass, increasing distance is - velocity
	var blobby_vel = (last_distance.x - distance)/delta
	var blobby_vert_vel = (last_distance.y - v_distance)/delta
	var direction: Vector2 = Vector2(sign(global_position.x - blobby.global_position.x + 6),0)
	# TODO This only gets more and more unreadable *facepalm*
	var power = smoothstep(radius, 0, distance)
	var v_power = smoothstep(v_radius, 0, v_distance)
	var draft_power = smoothstep(draft_radius, radius, distance)

	if (distance >= radius && distance <= draft_radius  && blobby_vel < -0.1 && v_distance < 14):
		displacement_coeff += direction * (draft_power/radius) * blobby_vel * interact_power
		saved_displacement = displacement_coeff.x
		is_idle_swinging = false
		$Timer.stop()
	
	# TODO v_distance could be a problem for upside down stuff
	elif (distance < radius && distance > 1 && abs(blobby_vel) > 0.1 && v_distance < 14 && abs(blobby_vert_vel) < 0.1):
		displacement_coeff += direction * power/radius * 0.3 * blobby_vel * interact_power
		displacement_coeff += direction * power * 2 * interact_power
		saved_displacement = displacement_coeff.x
		is_idle_swinging = false
		$Timer.stop()

	elif (v_distance < v_radius && distance < radius && abs(blobby_vert_vel) > 0.1):
		displacement_coeff += direction * v_power/v_radius * blobby_vert_vel * interact_power
		saved_displacement = displacement_coeff.x
		is_idle_swinging = false
		$Timer.stop()

	else:
		if(abs(displacement_coeff.x) > 0.1 && !is_idle_swinging || !$Timer.is_stopped()):
			if($Timer.is_stopped()):
				saved_displacement = displacement_coeff.x
				$Timer.start()
			var t = $Timer.get_wait_time() - $Timer.get_time_left()
			displacement_coeff.x = saved_displacement * exp(-0.66 * t) * cos(t * 3.0 * rand)
			start_swing_time = time
			begin_idle = true
		else:
			$Timer.stop()
			is_idle_swinging = true
			var start = displacement_coeff.x if begin_idle else 0.0
			displacement_coeff.x = start * exp(-0.2 * (time-start_swing_time)) + 0.3 * -sin(2.0*(time - start_swing_time))
			begin_idle = false
   # if(displacement_coeff.x > saved_coeff):
   #     print(displacement_coeff.x)
   #     saved_coeff = displacement_coeff.x
	for polygon in get_children():
		displacement_coeff.x = clamp(displacement_coeff.x, -max_displacement, max_displacement)
		if polygon is Polygon2D:
			polygon.material.set_shader_param("displacement_coefficient_x",
			 displacement_coeff.x)
			break

	last_distance = Vector2(distance, v_distance)
	time += delta


func _on_Area2D_body_entered(body: Node) -> void:
	var sound_index = round(rand_range(0,grass_sounds.size())) - 1
	if(body.is_in_group("player")):
		GlobalAudio.play_scene_independent(grass_sounds[sound_index], "Effects", -22, true, 0, true, 1)
	else:
		$AudioStreamPlayer2D.play()
