class_name IllusionaryWall
extends Node3D


@export var locked: bool = false: set = set_locked
@export var inverse: bool = false
@export var dissolve_duration: float = 0.45
@export var static_body: StaticBody3D
@export var mesh: MeshInstance3D
@export_group("Areas")
@export var appear_area: Area3D:
	set(value):
		if is_instance_valid(appear_area):
			appear_area.body_exited.disconnect(_on_appear_area_body_exited)

		appear_area = value

		if not appear_area.is_node_ready():
			await appear_area.ready

		appear_area.body_exited.connect(_on_appear_area_body_exited)
@export var disappear_area: Area3D:
	set(value):
		if is_instance_valid(disappear_area):
			disappear_area.body_entered.disconnect(_on_disappear_area_body_entered)

		disappear_area = value

		if not disappear_area.is_node_ready():
			await disappear_area.ready

		disappear_area.body_entered.connect(_on_disappear_area_body_entered)


func _ready() -> void:
	force_update()


func set_locked(value: bool) -> void:
	locked = value
	force_update()


func unlock() -> void:
	locked = false


func force_update() -> void:
	if disappear_area.overlaps_body(GameGlobals.get_player()):
		(disappear if not inverse else appear).call()
	elif not appear_area.overlaps_body(GameGlobals.get_player()):
		(appear if not inverse else disappear).call()


func disappear() -> void:
	assert(is_instance_valid(mesh), "'mesh' needs to be set.")

	if locked:
		return

	if is_instance_valid(static_body):
		static_body.process_mode = Node.PROCESS_MODE_DISABLED

	var tween: Tween = create_tween()
	tween.tween_property(mesh, ^"material_override:shader_parameter/alpha_scissor_threshold", 1.0, dissolve_duration)


func appear() -> void:
	assert(is_instance_valid(mesh), "'mesh' needs to be set.")

	if is_instance_valid(static_body):
		static_body.process_mode = Node.PROCESS_MODE_INHERIT

	var tween: Tween = create_tween()
	tween.tween_property(mesh, ^"material_override:shader_parameter/alpha_scissor_threshold", 0.0, dissolve_duration)


func _on_appear_area_body_exited(body: Node3D) -> void:
	if body == GameGlobals.get_player():
		force_update()


func _on_disappear_area_body_entered(body: Node3D) -> void:
	if body == GameGlobals.get_player():
		force_update()
