extends Control
class_name EventPlayerContainer

signal scene_change_finished()
signal sequence_changed(sequence) # warning-ignore:unused_signal
signal options_shown(options)
signal scene_change_started()
signal minigame_started(minigame, initial_state)

const EventPlayerScene = preload("res://scenes/ui/EventPlayer.tscn")

var allow_fade_skip := false

var _event_player_scene : EventPlayer = null
var _changing_scenes := false

func _ready() -> void:
	set_input_disabled(true)
	SimpleState.state_changed.connect(_on_state_changed) # warning-ignore:return_value_discarded


func _on_state_changed(_name: String, _state: Dictionary) -> void:
	pass


func _input(event) -> void:
	var mouse_down = event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT
	var ui_accept =  event.is_action_pressed("ui_accept") and not event.is_echo()
	if (mouse_down or ui_accept) and allow_fade_skip:
		$FadePanel.skip()


func connect_events(scene) -> void:
	# Handled Events
	scene.fade_in_started.connect(_on_fade_in_started)
	scene.fade_out_started.connect(_on_fade_out_started)
	scene.scene_ended.connect(_on_scene_ended)
	scene.sequence_changed.connect(_on_sequence_changed)

	# Bubbled Events
	scene.minigame_started.connect(_on_minigame_started)


func add_to_tree(scene : EventPlayer) -> void:
	add_child(scene)
	move_child(scene, 0)


func run_scene(scene : EventPlayer, sequence : String, entry : String) -> void:
	MemoryState.seen_passage(sequence)
	scene.run(sequence, entry)


func restore_scene(scene : EventPlayer, sequence : String, entry : String) -> void:
	scene.restore(sequence, entry)


func run(sequence: String, entry: String = "intro") -> void:
	_event_player_scene = EventPlayerScene.instantiate()
	SimpleState.update("sequence", { current_sequence = sequence, current_line_id  = entry })

	show()
	connect_events(_event_player_scene)
	add_to_tree(_event_player_scene)
	run_scene(_event_player_scene, sequence, entry)


func restore_from_state() -> void:
	var sequence = SimpleState.state.sequence.current_sequence
	var entry = SimpleState.state.sequence.current_line_id
	_event_player_scene = EventPlayerScene.instantiate()

	show()
	connect_events(_event_player_scene)
	add_to_tree(_event_player_scene)
	restore_scene(_event_player_scene, sequence, entry)


func minigame_finished(result) -> void:
	if is_instance_valid(_event_player_scene):
		_event_player_scene.emit_signal("minigame_finished", result)


func _on_fade_out_started() -> void:
	allow_fade_skip = true
	if not $FadePanel.fade_shown:
		await $FadePanel.fade_out()

	if is_instance_valid(_event_player_scene):
		_event_player_scene.emit_signal("fade_finished")
	else:
		_on_fade_out_started()


func _on_fade_in_started() -> void:
	if $FadePanel.fade_shown:
		await $FadePanel.fade_in()


	allow_fade_skip = false
	if is_instance_valid(_event_player_scene):
		_event_player_scene.emit_signal("fade_finished")


func _on_scene_ended() -> void:
	if not _changing_scenes:
		stop()


# Bubble Up Events
func _on_minigame_started(minigame: String, initial_state: Dictionary) -> void:
	emit_signal("minigame_started", minigame, initial_state)


func _on_sequence_changed(scene: String, line: String = "intro") -> void:
	emit_signal("scene_change_started")
	_changing_scenes = true

	if not $FadePanel.fade_shown:
		await $FadePanel.fade_out()

	if is_instance_valid(_event_player_scene):
		if _event_player_scene.get_parent():
			_event_player_scene.get_parent().remove_child(_event_player_scene)
		_event_player_scene.queue_free()

	run(scene, line)

	if $FadePanel.fade_shown:
		await $FadePanel.fade_in()

	_changing_scenes = false
	_event_player_scene.emit_signal("change_scene_finished")
	emit_signal("scene_change_finished")


func _options_shown(options: Array) -> void:
	emit_signal("options_shown", options)


func stop() -> void:
	SimpleState.update("sequence",  { current_sequence = "NONE"
									, current_line_id  = ""
									, background       = []
									, dialogue_pos     = "left"
									, blackout_visible = false
									, dialogue_visible = false
									, characters       = {}
									})
	await $FadePanel.fade_out()

	if is_instance_valid(_event_player_scene):
		if _event_player_scene and _event_player_scene.get_parent():
			_event_player_scene.get_parent().remove_child(_event_player_scene)
		_event_player_scene.queue_free()

	await $FadePanel.fade_in()
	hide()

func hard_stop() -> void:
	if is_instance_valid(_event_player_scene):
		if _event_player_scene and _event_player_scene.get_parent():
			_event_player_scene.get_parent().remove_child(_event_player_scene)
		_event_player_scene.queue_free()


func set_input_disabled(value: bool) -> void:
	if is_instance_valid(_event_player_scene):
		_event_player_scene.set_input_disabled(value)
