## Virtual base class for all states.
## Extend this class and override its methods to implement a state.
@abstract class_name State extends Node

## Emitted when the state finishes and wants to transition to another state.
@warning_ignore("unused_signal")
signal finished(next_state_path: String, data: Dictionary)


## Universal paused state
const PAUSED = "Paused"

## For 'ghost frame' update fix
var is_active: bool = false:
	set(value):
		is_active = value
	get:
		return is_active


## Called by the state machine when receiving unhandled input events.
@abstract func _handle_input(event: InputEvent) -> void

## Called by the state machine on the engine's main loop tick.
@abstract func _state_update(delta: float) -> void

## Called by the state machine on the engine's physics update tick.
@abstract func _state_physics_update(delta: float) -> void

## Called by the state machine upon changing the active state. The `data` parameter
## is a dictionary with arbitrary data the state can use to initialize itself.
@abstract func _enter(previous_state_path: String, data: Dictionary[StringName, Variant] = {}) -> void

## Called by the state machine before changing the active state. Use this function
## to clean up the state.
@abstract func _exit() -> void


func handle_input(event: InputEvent) -> void:
	if not is_active: return
	_handle_input(event)


func state_update(delta: float) -> void:
	if not is_active: return
	_state_update(delta)


func state_physics_update(delta: float) -> void:
	if not is_active: return
	_state_physics_update(delta)


func enter(previous_state_path: String, data: Dictionary[StringName, Variant] = {}) -> void:
	is_active = true
	_enter(previous_state_path, data)
	

func exit() -> void:
	is_active = false
	_exit()
