@tool
@icon("res://textures/stickers/icon_sticker2.svg")
class_name Sticker extends Area2D
## Handle all the sticker-relative gameplay.
##
## Sticker node expect to be a child of a Node2D, who serve as a root for
## all the fonctionnalities. You need to assign nodes for the stickerdetection
## and for the sprites.

#region Exported variables
@export var Sticker_mode:bool = false
@export_group("Nodes")
## The look of the object. If it's multiple sprites, they should be under one main sprite
@export var WorldSprite:Sprite2D
## Optional - The look of the object when grabbed. If empty, OutlineMat will be applied to WorldSprite
@export var StickerSprite:Sprite2D 
## Optional - The detection zone, if not the same as the sticker area
@export var DetectionArea:Area2D:
	set(new_area):
		if(new_area != self):
			DetectionArea = new_area
		else:
			printerr("DetectionArea cannot be the sticker itself")
@export_group("Material")
@export var OutlineMat:ShaderMaterial = preload("res://shaders/shaderMaterial_Outline.tres")
@export var Foiled:bool #TODO: Foil material and logic
@export var CreateShape:bool:
	set(value):
		var test = CollisionShape2D.new()
		test.set_name("StickerShape")
		add_child(test)
		test.set_owner(get_tree().get_edited_scene_root())
		test = null
#endregion

var meta:PackedStringArray = ["sticker"]
var detected_solids:Array
var detected_zones:Array
var Grabbed:bool = false

## Emitted when the sticker overlap a blocking body, preventing to be spawned as an asset in the level. Usually received by the cursor to change his sprite
signal spawn_mode_changed(can_spawn:bool)
#region Functions
func _get_configuration_warnings():
	if (get_parent() == get_tree().get_edited_scene_root()):
		return ["This node should have a parent"]
	return []

func _init():
	collision_layer = 2
	# TODO: Stickerzone maybe will not need to check everything, and detection will be on the zone detection area only. maybe we want a fallback if sticker area and detection area are the same shape
	collision_mask = 61
	set_meta("tags",meta)
	monitoring = true
	if Engine.is_editor_hint():
			update_configuration_warnings()
	
func _enter_tree():
	set_meta("tags",meta)
	if (get_parent() is Sprite2D and WorldSprite == null):
		WorldSprite = get_parent()
	if Engine.is_editor_hint():
			update_configuration_warnings()

func _ready():
	if (get_parent() == get_tree().root):
		printerr("stickers should always have a parent")
		breakpoint
	if (DetectionArea != null):
		DetectionArea.area_entered.connect(_on_area_entered)
		DetectionArea.area_exited.connect(_on_area_exited)
		DetectionArea.body_entered.connect(_on_body_entered)
		DetectionArea.body_exited.connect(_on_body_exited)
		DetectionArea.collision_mask = 61
	else:
		area_entered.connect(_on_area_entered)
		area_exited.connect(_on_area_exited)
		body_entered.connect(_on_body_entered)
		body_exited.connect(_on_body_exited)
	

# TODO : Solids and interactive zone detection area should not be the same as the sticker area. 
# IDEA: Need to export a child Area2D
func _on_body_entered(body:Node2D):
	print("body entered",body)
	detected_solids.append(body)
	spawn_mode_changed.emit(false)
func _on_body_exited(body:Node2D):
	print("body exited",body)
	detected_solids.erase(body)
	if(Sticker_mode and Grabbed and detected_solids.size() == 0 ):
		spawn_mode_changed.emit(true)
func _on_area_entered(area:Area2D):
	print("area entered",area)
	#TODO:Filter by type
	detected_zones.append(area)
func _on_area_exited(area:Area2D):
	print("area exited",area)
	detected_zones.erase(area)

func _process(_delta):
	pass
			

## When the sticker is released
func on_released(_CastResult:Array=[]):
	print(self," released")
	Grabbed = false
	#Need a traceresult to know if it should stay in the stickerstate or be released in the world
	if(detected_solids.size()==0):
		get_parent().top_level = false
		disable_ChildNodes_collisions(false)
		update_ChildNodes_visibilty(true)
		Sticker_mode = false
		on_unhover() #security,but i don't like it
	get_parent().reparent(MapManager.current_scene.get_child(0))
	


func on_click():
	print(self," clicked")

func redraw():
	if (StickerSprite != null):
		StickerSprite.queue_redraw()
	if (WorldSprite != null):
		WorldSprite.queue_redraw()
		
func on_hover():
	if (Sticker_mode == false):
		if (StickerSprite != null):
			WorldSprite.visible = false
			StickerSprite.visible = true
		elif (WorldSprite != null):
			WorldSprite.material = OutlineMat
		redraw()
	

func on_unhover():
	if (Sticker_mode == false):
		if (StickerSprite != null):
			StickerSprite.visible = false
		if (WorldSprite != null):
			WorldSprite.material = null
			WorldSprite.visible = true
		redraw()
	

func on_grab(_offset:Vector2=Vector2(0.0,0.0)):
	Sticker_mode = true
	
	get_parent().top_level = true
	get_parent().reparent(MapManager)
	update_ChildNodes_visibilty(false)
	disable_ChildNodes_collisions(true)
	Grabbed = true

func update_ChildNodes_visibilty(_visible:bool=true):
	for _childNode in get_parent().get_children():
		if(_childNode != WorldSprite and _childNode != StickerSprite):
			_childNode.visible = _visible

func disable_ChildNodes_collisions(_disable:bool=true):
	for _childNode in get_parent().get_children():
		if (_childNode != self):
			_childNode.process_mode = Node.PROCESS_MODE_DISABLED if _disable else Node.PROCESS_MODE_ALWAYS

#endregion
