extends Control

# Autoload named Lobby

# These signals can be connected to by a UI lobby scene or the game scene.
signal player_connected(peer_id, player_info)
signal player_disconnected(peer_id)
signal server_disconnected

const PORT = 7000
const DEFAULT_SERVER_IP = "127.0.0.1" # IPv4 localhost
const MAX_CONNECTIONS = 20
@onready var address_input: TextEdit = $TextEdit
var players = {}
var my_random_number = RandomNumberGenerator.new().randf_range(-2.0, 2.0)
var player_info = {"name": str(my_random_number)}
var players_loaded = 0

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	multiplayer.peer_connected.connect(_on_player_connected)
	multiplayer.peer_disconnected.connect(_on_player_disconnected)
	multiplayer.connected_to_server.connect(_on_connected_ok)
	multiplayer.connection_failed.connect(_on_connected_fail)
	multiplayer.server_disconnected.connect(_on_server_disconnected)
	
	var map_dir := DirAccess.open("res://scenes/maps/maps/")
	if map_dir:
		map_dir.list_dir_begin()
		var file_name = map_dir.get_next()
		while file_name != "":
			$Maps.add_item(file_name)
			file_name = map_dir.get_next()

func join_game(address = ""):
	address = address_input.text
	var peer = ENetMultiplayerPeer.new()
	var error = peer.create_client(address, PORT)
	if error:
		return error
	multiplayer.multiplayer_peer = peer
	
	
func create_game():
	var peer = ENetMultiplayerPeer.new()
	var error = peer.create_server(PORT, MAX_CONNECTIONS)
	if error:
		return error
	multiplayer.multiplayer_peer = peer
	players[1] = player_info
	player_connected.emit(peer.get_unique_id(), player_info)


func remove_multiplayer_peer():
	multiplayer.multiplayer_peer = null

# When the server decides to start the game from a UI scene,
# do Lobby.load_game.rpc(filepath)
@rpc("call_local", "reliable")
func load_game():
	var chosen_map_index = $Maps.get_selected_items()[0]
	var chosen_map = $Maps.get_item_text(chosen_map_index)
	var path_tmpl := "res://scenes/maps/maps/%s"
	var path := path_tmpl % chosen_map
	get_tree().change_scene_to_file(path)

# Every peer will call this when they have loaded the game scene.
@rpc("any_peer", "call_local", "reliable")
func player_loaded():
	if multiplayer.is_server():
		players_loaded += 1
		players_loaded = players.size()
		if players_loaded == players.size():
			#$/root/Game.start_game()
			players_loaded = 0
			
# When a peer connects, send them my player info.
# This allows transfer of all desired data for each player, not only the unique ID.
func _on_player_connected(id):
	player_info = {"name": multiplayer.get_unique_id(), "health": 100}
	_register_player.rpc_id(1, multiplayer.get_unique_id(), player_info)
	
@rpc("any_peer", "reliable")
func _register_player(id: int, new_player_info):
	var new_player_id: int = 1
	if not multiplayer.is_server():
		new_player_id = 1
	else:
		new_player_id = multiplayer.get_remote_sender_id()
	players[id] = new_player_info
	GameServerManager.players[id] = new_player_info
	#player_info = {"name": str(multiplayer.get)}
	player_connected.emit(id, new_player_info)

	
func _on_player_disconnected(id):
	players.erase(id)
	player_disconnected.emit(id)


func _on_connected_ok():
	var peer_id = multiplayer.get_unique_id()
	players[peer_id] = player_info
	player_connected.emit(peer_id, player_info)


func _on_connected_fail():
	multiplayer.multiplayer_peer = null


func _on_server_disconnected():
	multiplayer.multiplayer_peer = null
	players.clear()
	server_disconnected.emit()
# Called every frame. 'delta' is the elapsed time since the previous frame.

func _on_host_pressed() -> void:
	player_info = {"name":  str(1), "health": 100}
	_register_player(1, player_info)
	create_game()

func _on_join_pressed() -> void:
	join_game()

func _on_start_pressed() -> void:
	load_game.rpc()
func _process(delta: float) -> void:
	pass
