extends PanelContainer

const RANDOM_PLAYER_COLORS := [
	Color.LIGHT_CORAL,
	Color.GOLDENROD,
	Color.KHAKI,
	Color.AQUAMARINE,
	Color.SKY_BLUE,
	Color.VIOLET,
]

const MIN_PLAYERS := 2

@export var player_setup_scene: PackedScene

@onready var map_select: ItemList = %MapSelect

@onready var start_button: Button = %Start

@onready var player_setup_list: HBoxContainer = %PlayerSetupList

@onready var game: Game = get_tree().get_first_node_in_group(Game.group)


func play_chime() -> void:
	game.sfx.chime.play()


func _ready() -> void:
	# Populate map selection
	for level: Level in Level.catalog.levels:
		map_select.add_item(level.level_name, level.preview)

	check_start_conditions()


func _input(event: InputEvent) -> void:
	if event.is_action_pressed("ui_start"):
		add_player(InputMethod.get_method(event))


## Close menu without starting game.
func cancel() -> void:
	queue_free()


## Start with the current game configuration.
func start() -> void:
	var player_list := players()
	var level := selected_level()
	var init_world := func(world: World) -> void:
		world.manager = RoundRobinManager.new()
		world.manager.players = player_list
		world.initial_level = level.scene
	game.queue_scene(World.SCENE).then(init_world)


## Returns the `Level` selected by the user if there is one, or `null` if no level is selected.
func selected_level() -> Level:
	var selections := map_select.get_selected_items()
	if selections:
		return Level.catalog.levels[selections[0]]
	return null


## Build the array of players represented by the selections made here.
func players() -> Array[WorldPlayer]:
	var arr: Array[WorldPlayer] = []
	arr.assign(
		player_setup_list.get_children().map(
			func(s: PlayerSetup) -> WorldPlayer: return s.build_player()
		)
	)
	return arr


## Add a new PlayerSetup node for the given input method.
func add_player(input_method: InputMethod.Type) -> void:
	var instance: PlayerSetup = player_setup_scene.instantiate()
	instance.input_method = input_method
	instance.player_color = RANDOM_PLAYER_COLORS.pick_random()
	player_setup_list.add_child(instance)
	instance.tree_exited.connect(check_start_conditions)
	check_start_conditions()


func _can_start() -> bool:
	return selected_level() and len(players()) >= MIN_PLAYERS


## Check if the game can be started with the current selection,
## and set the start button status appropriately.
func check_start_conditions() -> void:
	start_button.disabled = not _can_start()


func _on_add_player_button_pressed() -> void:
	add_player(InputMethod.Type.MOUSE_KEYBOARD)
