@tool
extends Node

@export_range(0.1, 10, 0.01) var height: float = 2.0
@export_range(0.1, 10, 0.01) var width: float = 1.0
## Player camera's NEAR clip distance
@export_range(0, 0.2, 0.001) var indent: float = 0.1

@export var portal: Portal
@export var portal_material: BaseMaterial3D


func _add_inspector_buttons() -> Array:
	var buttons: Array = []
	
	buttons.push_back({
		"name": "Generate Portal Mesh",
		"pressed": generate_portal_mesh
	})
	buttons.push_back({
		"name": "Remove Mesh",
		"pressed": func(): portal.mesh = null
	})
	
	return buttons

func _get_configuration_warnings() -> PackedStringArray:
	var warnings: Array = []
	
	if portal == null:
		warnings.append("Assign a portal to generate the mesh for")
	
	return warnings

func generate_portal_mesh() -> void:
	if portal == null:
		push_error("No portal")
		return
	
	if portal.mesh != null:
		push_warning("The portal %s already has a mesh! Replacing." % portal.name)
		portal.mesh = null
		
	
	var mesh = ArrayMesh.new()
	print("[PMM] Creating mesh")
	
	var surface_array: Array = []
	surface_array.resize(Mesh.ARRAY_MAX)
	
	var verts: PackedVector3Array = PackedVector3Array()
	var uvs: PackedVector2Array = PackedVector2Array()
	var normals: PackedVector3Array = PackedVector3Array()
	var indices: PackedInt32Array = PackedInt32Array()
	
	# Just to save some chars
	var w: float = width / 2
	var h: float = height / 2
	
	
	# Outside rect
	var TOP_LEFT: Vector3 = Vector3(-w, h, 0)
	var TOP_RIGHT: Vector3 = Vector3(w, h, 0)
	var BOTTOM_LEFT: Vector3 = Vector3(-w, -h, 0)
	var BOTTOM_RIGHT: Vector3 = Vector3(w, -h, 0)
	# Inside rect, indented
	var INDENT_TL: Vector3 = TOP_LEFT + Vector3(indent, -indent, -indent)
	var INDENT_TR: Vector3 = TOP_RIGHT + Vector3(-indent, -indent, -indent)
	var INDENT_BL: Vector3 = BOTTOM_LEFT + Vector3(indent, indent, -indent)
	var INDENT_BR: Vector3 = BOTTOM_RIGHT + Vector3(-indent, indent, -indent)
	
	verts.append_array([
		TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT,
		INDENT_TL, INDENT_TR, INDENT_BL, INDENT_BR
		])
	
	var ix: float = indent / width
	var iy: float = indent / height
	uvs.append_array([
		Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), # Outside UVs
		Vector2(ix, iy), Vector2(1-ix, iy), Vector2(ix, 1-iy), Vector2(1-ix, 1-iy) # Indented UVs
		])
	
	# We are going for a flat-surface look here. Portals should be unshaded anyways.
	normals.append_array([
		Vector3.BACK, Vector3.BACK, Vector3.BACK, Vector3.BACK,
		Vector3.BACK, Vector3.BACK, Vector3.BACK, Vector3.BACK
		])
	
	# 0 ----------- 1
	# | \         / |
	# |  4-------5  |
	# |  |       |  |
	# |  |       |  |
	# |  6-------7  |
	# | /         \ |
	# 2 ----------- 3
	
	# Triangles are clockwise!
	
	indices.append_array([
		0, 1, 4,
		4, 1, 5, # Top section done
		1, 3, 5,
		5, 3, 7, # right section done
		3, 2, 7,
		7, 2, 6, # bottom section done
		2, 0, 6,
		6, 0, 4, # left section done
		
		4, 5, 6,
		6, 5, 7, # middle sectiondone
		]) 
	
	surface_array[Mesh.ARRAY_VERTEX] = verts
	surface_array[Mesh.ARRAY_TEX_UV] = uvs
	surface_array[Mesh.ARRAY_NORMAL] = normals
	surface_array[Mesh.ARRAY_INDEX] = indices
	
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)
	if portal_material:
		mesh.surface_set_material(0, portal_material)
	mesh.surface_set_name(0, "Portal Material")
	portal.mesh = mesh
	
	print("[PMM] Mesh assigned")
