extends Node

@export var outer_polygon: PackedVector2Array
@export var inner_polygons: Array[PackedVector2Array]
@export var edge_non_fracture: float = 0.1

@onready var camera: Camera3D = get_node("/root/Node3D/Camera3D")
@onready var meshInstance = MeshInstance3D.new()
@onready var parentNode = get_node("..")

var depth: float:
	set(value):
		if value > 0:
			depth = -value
		depth = value

var static_body: StaticBody3D

func _ready() -> void:
	assert(camera, "camera was not found")
	assert(len(outer_polygon) > 2, "outer polygon does not meet the required length")
	
	camera.connect("wall_hit", _handle_hit_signal)
	
	self.add_child(meshInstance)
	_draw()

func _draw():
	var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons)
	var vectors = []
	
	vectors.append_array(outer_polygon)
	for ip in inner_polygons:
		vectors.append_array(ip)
	
	var meshGenerator = GeoPolyMesh.new(vector_indexes, vectors)
	var mesh = meshGenerator.commit_mesh()
	
	meshInstance.mesh = mesh
	meshInstance.create_trimesh_collision()
	static_body = _find_static_body()

func _re_draw():
	meshInstance.remove_child(static_body)
	static_body.queue_free()
	
	var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons)
	var vectors = []
	
	vectors.append_array(outer_polygon)
	for ip in inner_polygons:
		vectors.append_array(ip)
	
	var meshGenerator = GeoPolyMesh.new(vector_indexes, vectors)
	var mesh = meshGenerator.commit_mesh()
	
	meshInstance.mesh = mesh
	meshInstance.create_trimesh_collision()
	static_body = _find_static_body()


func _handle_hit_signal(wall_id: int, position: Vector3, cutter: PackedVector2Array):
	# validate that the hit was to this wall, if not return
	if wall_id != static_body.get_instance_id():
		return

	var hole_position_offset = self.position + position
	var hole_vector2_offset = Vector2(hole_position_offset.x, hole_position_offset.y)
	
	# translate the cutter
	var hole_vectors = Transform2D(0, hole_vector2_offset) * cutter
	
	_add_hole(hole_vectors)
	
	_re_draw()

func _add_hole(new_hole: PackedVector2Array):
	var values_to_remove = []
	
	var merged: PackedVector2Array = new_hole
	for index in range(len(self.inner_polygons)):
		var result = Geometry2D.merge_polygons(merged, self.inner_polygons[index])
		
		if len(result) == 1:
			merged = result[0]
			values_to_remove.append(self.inner_polygons[index])
		elif len(result) > 1:
			# need to check that they have no overlapping area if they do clip
			var overlap = Geometry2D.intersect_polygons(result[0], result[1])
			
			if len(overlap) != 0:
				merged = Geometry2D.clip_polygons(result[0], result[1])[0]
				values_to_remove.append(self.inner_polygons[index])
	
	for i in values_to_remove:
		self.inner_polygons.erase(i)
	
	inner_polygons.append(merged)

func _find_static_body():
	for child in meshInstance.get_children():
		if child is StaticBody3D:
			return child
