# Hurry Curry! - a game about cooking
# Copyright (C) 2025 Hurry Curry! contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
extends Control
class_name Lobby

const MAX_BOT_COUNT_PER_TYPE: int = 3
const PLAYER = preload("res://gui/overlays/lobby/player.tscn")

var map_count
var selected_map := 0
var selected_map_name: String

var bots_enabled := false
var bot_counts := {}
var bot_reset_buttons := {}
var bot_inc_buttons := {}
var bot_dec_buttons := {}

@onready var game: Game = $"../../Game" # TODO
@onready var player_container = $PlayerList/VBoxContainer/Players

@onready var map_name_label = $Sidebar/Bottom/MarginContainer/VBoxContainer/HBoxContainer/Map/Name
@onready var map_player_label = $Sidebar/Bottom/MarginContainer/VBoxContainer/HBoxContainer/Map/Players
@onready var map_difficulty_label = $Sidebar/Bottom/MarginContainer/VBoxContainer/HBoxContainer/Map/Difficulty
@onready var map_list_container = $Sidebar/Bottom/MarginContainer/VBoxContainer/MapList/VBoxContainer

@onready var prev_map = $Sidebar/Bottom/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Left
@onready var next_map = $Sidebar/Bottom/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/Right

@onready var bots_container = $Sidebar/Bottom/MarginContainer/VBoxContainer/Bots
@onready var bot_settings = $Sidebar/Bottom/MarginContainer/VBoxContainer/Bots/ScrollContainerCustom/BotSettings
@onready var bot_settings_conainer = $Sidebar/Bottom/MarginContainer/VBoxContainer/Bots/ScrollContainerCustom

func _ready():
	game.update_players.connect(update_players)
	initialize()
	game.data_updated.connect(initialize)
	game.join_state_updated.connect(_update_visible)
	game.in_lobby_updated.connect(_update_visible)
	_update_visible(false)
	check_for_music()

func initialize():
	map_count = game.maps.size()
	
	for c in map_list_container.get_children():
		c.queue_free()
	for c in bot_settings.get_children():
		c.queue_free()
	
	var i := 0
	for m in game.maps:
		var b := Button.new()
		b.name = m[0]
		b.text = "%s (%d)" % [m[1]["name"], m[1]["players"]]
		b.pressed.connect(select_map.bind(i))
		b.focus_entered.connect(select_map.bind(i))
		map_list_container.add_child(b)
		i += 1
	select_map(0)
	
	for algo_id: String in game.bot_algos:
		if algo_id == "customer" or algo_id == "test":
			continue
		
		bot_counts[algo_id] = 0
		
		var h := HBoxContainer.new()
		h.name = algo_id
		var add := Button.new()
		add.text = "+"
		var reset := Button.new()
		reset.size_flags_horizontal = SIZE_EXPAND_FILL
		var remove := Button.new()
		remove.text = "-"
		bot_reset_buttons[algo_id] = reset
		bot_inc_buttons[algo_id] = add
		bot_dec_buttons[algo_id] = remove
		update_bot_reset_text(algo_id)
		add.pressed.connect(increase_bot_count.bind(algo_id))
		reset.pressed.connect(reset_bot_count.bind(algo_id))
		remove.pressed.connect(decrease_bot_count.bind(algo_id))
		h.add_child(remove)
		h.add_child(reset)
		h.add_child(add)
		bot_settings.add_child(h)

func select_map(i: int):
	if i >= map_count:
		return
	selected_map = i
	var map_data: Dictionary = game.maps[i][1]
	map_name_label.text = map_data["name"]
	map_player_label.text = tr("c.map.players_recommended").format([roundi(map_data["players"])])
	map_difficulty_label.text = tr("c.map.difficulty.%d" % (map_data["difficulty"] - 1))
	selected_map_name = game.maps[i][0]
	if not game.menu.covered:
		map_list_container.get_child(i).grab_focus()

func increase_bot_count(algo_id: String):
	bot_counts[algo_id] += 1
	update_bot_reset_text(algo_id)

func decrease_bot_count(algo_id: String):
	bot_counts[algo_id] -= 1
	update_bot_reset_text(algo_id)

func reset_bot_count(algo_id: String):
	bot_counts[algo_id] = 0
	update_bot_reset_text(algo_id)

func update_bot_reset_text(algo_id: String):
	var display_name: String = tr("s.bot.%s" % algo_id)
	bot_reset_buttons[algo_id].text = "%s (%d)" % [display_name, bot_counts[algo_id]]
	bot_inc_buttons[algo_id].disabled = not bot_counts[algo_id] < MAX_BOT_COUNT_PER_TYPE
	bot_dec_buttons[algo_id].disabled = not bot_counts[algo_id] > 0

func update_players(player_list: Dictionary):
	for i in player_container.get_children():
		i.queue_free()

	for i in player_list.keys():
		var p: PlayerTag = PLAYER.instantiate()
		player_container.add_child(p)
		p.setup(player_list[i].username)

func _input(_event):
	if not visible:
		return

	if Input.is_action_just_pressed("previous") and not prev_map.disabled:
		prev_map.emit_signal("pressed")
	elif Input.is_action_just_pressed("next") and not next_map.disabled:
		next_map.emit_signal("pressed")

func _on_left_pressed():
	selected_map = (selected_map - 1) % map_count
	select_map(selected_map)

func _on_right_pressed():
	selected_map = (selected_map + 1) % map_count
	select_map(selected_map)

func _on_start_pressed():
	if selected_map_name != null:
		var start_msg := "/start %s" % selected_map_name
		
		if bots_enabled:
			for k in bot_counts.keys():
				for i in range(bot_counts[k]):
					start_msg += "\ncreate-bot %s" % k
		
		game.mp.send_chat(game.my_player_id, start_msg)
		Sound.set_music(null) # TODO: Game music enter

func _update_visible(_state: bool):
	visible = game.in_lobby and game.join_state == Game.JoinState.JOINED

func check_for_music():
	if visible:
		Sound.set_music(null) # TODO: lobby music
	else:
		Sound.set_music(null)

func _on_enable_bots_toggled(toggled_on):
	bots_enabled = toggled_on
	bot_settings_conainer.visible = toggled_on
	bots_container.size_flags_vertical = SIZE_EXPAND_FILL if toggled_on else SIZE_FILL
