extends Node
class_name PlayerStateMachine

signal StateChanged

enum States {
	UNSET, IDLE, WALKING, USING_ITEM_A, DRAWING_BOW, FIRING_ARROW,
	SITTING, CUTSCENE, PLAY_ANIMATION
}

@export var states_container: Node
@export var current_state: BaseState

var state_dict := {}
var queued_state: PlayerStateMachine.States = PlayerStateMachine.States.UNSET
var queued_parameters: Dictionary = {}

# Public Methods
func GetCurrentStateEnum() -> States:
	return current_state.GetStateEnum()


func QueueStateChange(to_state_enum: PlayerStateMachine.States, extra_parameters: Dictionary = {}) -> void:
	queued_state = to_state_enum
	queued_parameters = extra_parameters


func SendEventToCurrentStateIfValid(signal_name: String, parameters: Variant = null) -> void:
	if current_state._subscribed_events.has(signal_name):
		current_state._StateMachine_OnEventSent(signal_name, parameters)


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	var children := states_container.get_children()
	for child in children:
		if child is not BaseState:
			continue
		var state := child as BaseState
		state_dict[state.GetStateEnum()] = state
	
	if current_state:
		current_state.Enter({})


func _process(delta: float) -> void:
	if current_state:
		current_state.Update(delta)
	
	if queued_state != PlayerStateMachine.States.UNSET:
		_swap_state()


func _swap_state() -> void:
	if current_state:
		current_state.Exit()
		
	current_state = state_dict[queued_state] as BaseState
	current_state.Enter(queued_parameters)
	queued_state = PlayerStateMachine.States.UNSET
	queued_parameters = {}
	
	StateChanged.emit()
