extends Area2D
class_name Ghost
## Ghost previewing the instantiation of a scene.


## Color to modulate this with if the body currently isn't overlapping anything.
@export var valid_color: Color = Color.WHITE

## Color to modulate this with if the body currently is overlapping something.
@export var invalid_color: Color = Color.RED


## The [Instantiator] to use to spawn the ghosted item.
@onready var instantiator: Instantiator = $Instantiator

## The [OverlapChecker] to use to see if a solid block is overlapping the ghost.
@onready var overlap_checker: OverlapChecker = $OverlapChecker

## The [PlaceableAreaChecker] to use to see if the ghost is currently inside the placeable area.
@onready var placeable_area_checker: PlaceableAreaChecker = $PlaceableAreaChecker

## The [OverlapFreer] to use to delete the [PhysicsBody2D] behind the ghost before instantiation.
@onready var overlap_freer: OverlapFreer = $OverlapFreer

## The [CollisionShape2D] to use to check for placement checks.
##
## MUST consist of a [RectangleShape2D].
@onready var placement_shape: CollisionShape2D = $PlacementShape

## The [Sprite2D] node previewing the scene.
@onready var preview_sprite: Sprite2D = $PlacementShape/PreviewSprite

## The collision mask of objects that should prevent this object's placement.
@export_flags_2d_physics var collision_mask_prevent_placement: int

## The collision mask of objects that should be deleted on this object's placement.
@export_flags_2d_physics var collision_mask_delete_placement: int

## The texture that the preview sprite should display. 
@export var preview_texture: Texture2D:
	get:
		return preview_texture
	set(value):
		preview_texture = value
		# Quick priority fix
		if preview_sprite:
			preview_sprite.texture = value


func _ready():
	collision_mask = collision_mask_prevent_placement | collision_mask_delete_placement
	preview_sprite.texture = preview_texture


func _physics_process(_delta: float):
	# Update collision
	update_can_place()


var can_place: bool:
	get:
		return can_place
	set(value):
		can_place = value
		modulate = valid_color if value else invalid_color


## Update the value of [can_place].
# DIRTY HACK: Relies on the placeable area being perfectly surrounded by solid bodies.
func update_can_place() -> void:
	can_place = overlap_checker.is_overlapping_with == null and placeable_area_checker.is_overlapping_with != null


func materialize():
	# Compatibility stub for Instantiator
	if not can_place:
		return null
	var overlapping_bodies = get_overlapping_bodies()
	for body in overlapping_bodies:
		if body is PhysicsBody2D:
			if body.collision_layer & collision_mask_delete_placement:
				body.queue_free()
	var inst = instantiator.instantiate()
	# TODO: Remove this
	return inst