extends Node2D

export (NodePath) var polygon_shard_path
onready var polygon_shard = get_node(polygon_shard_path)
onready var shard_texture = polygon_shard.texture
onready var shard_script = preload("res://JuiceMaster/Shard.gd")

var polygon_clipper = Polygon2D.new()

export (NodePath) var viewport_path 
onready var viewport = get_node(viewport_path)
onready var resolution = viewport.size



func _ready():
	randomize()
	# make the first shard a perfect rectangle filling the screen
	var new_points : PoolVector2Array
	new_points.append(Vector2(0,0))
	new_points.append(Vector2(resolution.x, 0))
	new_points.append(Vector2(resolution.x, resolution.y))
	new_points.append(Vector2(0,resolution.y))
	polygon_shard.polygon = new_points
	pass

#func _process(delta):
#	if Input.is_action_just_pressed("l_click"):
#		split_at_position(get_local_mouse_position(), Vector2.RIGHT.rotated(randf()*TAU))
#	elif Input.is_action_just_pressed("r_click"):
#		split_all(get_local_mouse_position(), Vector2.RIGHT.rotated(randf()*TAU))
#	pass

func split_polygon(split_this, point, direction):
	if split_this != null:
		# fix situations where no intersections with sides exist
		if direction.normalized() == Vector2.RIGHT or direction.normalized() == Vector2.LEFT or direction.normalized() == Vector2.UP or direction.normalized() == Vector2.DOWN:
			direction = direction.rotated(0.01)

		# fix situations where point is outside screen
		point.x = clamp(point.x, 0, resolution.x)
		point.y = clamp(point.y, 0, resolution.y)
		
		# generate the clipping polygon that splits the screen in 2 parts
		
		# generate helper positions on sides and corners of screen
		var left = Geometry.line_intersects_line_2d(point, direction, Vector2.ZERO, Vector2.DOWN)
		var up = Geometry.line_intersects_line_2d(point, direction, Vector2.ZERO, Vector2.RIGHT)
		var right = Geometry.line_intersects_line_2d(point, direction, resolution, Vector2.UP)
		var down = Geometry.line_intersects_line_2d(point, direction, resolution, Vector2.LEFT)
		
		# find which intersections of screen edge happened
		var left_valid = left.y >= 0 and left.y < resolution.y
		var up_valid = up.x > 0 and up.x <= resolution.x
		var right_valid = right.y > 0 and right.y <= resolution.y
		var down_valid = down.x >= 0 and down.x < resolution.x
		
		var corner_offset = 20
		var up_left = Vector2.ZERO + Vector2(-1,-1) * corner_offset
		var up_right = Vector2(resolution.x, 0) + Vector2(1,-1) * corner_offset
		var down_left = Vector2(0, resolution.y) + Vector2(-1,1) * corner_offset
		var down_right = resolution + Vector2(1,1) * corner_offset
		
		# assemble shape based on where the line intersected the borders
		var new_clipper_shape: PoolVector2Array
		
		if left_valid and right_valid:
			new_clipper_shape.append(left)
			new_clipper_shape.append(up_left)
			new_clipper_shape.append(up_right)
			new_clipper_shape.append(right)
			#horizontal
			pass
		elif left_valid and down_valid:
			new_clipper_shape.append(left)
			new_clipper_shape.append(down)
			new_clipper_shape.append(down_left)
			#down left corner
			pass
		elif left_valid and up_valid:
			new_clipper_shape.append(left)
			new_clipper_shape.append(up_left)
			new_clipper_shape.append(up)
			#up left corner
			pass
		elif up_valid and down_valid:
			#vertical
			new_clipper_shape.append(up)
			new_clipper_shape.append(down)
			new_clipper_shape.append(down_left)
			new_clipper_shape.append(up_left)
			pass
		elif up_valid and right_valid:
			new_clipper_shape.append(up)
			new_clipper_shape.append(right)
			new_clipper_shape.append(down_right)
			new_clipper_shape.append(down_left)
			new_clipper_shape.append(up_left)
			#up right corner
			pass
		elif down_valid and right_valid:
			new_clipper_shape.append(right)
			new_clipper_shape.append(down)
			new_clipper_shape.append(down_left)
			new_clipper_shape.append(up_left)
			new_clipper_shape.append(up_right)
			#down right corner
			pass
		else:
			print("exception: point likely outside the screen")
		
		polygon_clipper.polygon = new_clipper_shape
		
		# get the shard on one side of the polygon
		var	new_shards = Geometry.clip_polygons_2d(split_this.polygon, polygon_clipper.polygon)
		
		# get the shard on the other side of the polygon
		new_shards += Geometry.intersect_polygons_2d(split_this.polygon, polygon_clipper.polygon)
		
		# spawn new shards as children of the polygon
		for shard_polygon in new_shards:
			# configure shard
			var new_shard = Polygon2D.new()
			new_shard.polygon = shard_polygon
			new_shard.texture = shard_texture
			new_shard.add_to_group("shards")
			new_shard.set_script(shard_script)
			new_shard.depth = split_this.depth + 1
			
			# spawn shard
			split_this.add_child(new_shard)

		# inform the polygon that it has been split
		split_this.split(1)
		
	pass

func find_polygon_at_position(point):
	# check which polygon is at the position
	# assumes none of them moved resulting in one always being found
	var shards = get_tree().get_nodes_in_group("shards")
	for shard in shards:
		if Geometry.is_point_in_polygon(point,shard.polygon):
			return(shard)
	pass

func split_all(point, direction):
	# splits all shards in half
	var shards = get_tree().get_nodes_in_group("shards")
	for shard in shards:
		split_polygon(shard, point, direction)

func split_at_position(point, direction):
	# proxy for finding a polygon and splitting it, 2 in 1
	split_polygon(find_polygon_at_position(point), point, direction)
	pass

func shatter_at_position(point, full_splits, shard_splits, shard_radius):
	for i in range(full_splits):
		var direction = Vector2.RIGHT.rotated((randf() * TAU * 0.1) + i*TAU/full_splits )
		split_all(point + direction*10.0, direction)
	for i in range(shard_splits):
		var offset = Vector2.RIGHT.rotated((randf() * TAU * 0.1) + i*TAU/shard_splits )*shard_radius*( pow(randf(),3) + 0.1)
		var direction = offset.rotated((rand_range(-0.1,0.1)+ 0.25) * TAU ).normalized()
		split_at_position(point+offset, direction)
	pass
