extends Node3D

@onready var skin_input: LineEdit = $Menu/MainContainer/MainMenu/Option2/SkinInput
@onready var nick_input: LineEdit = $Menu/MainContainer/MainMenu/Option1/NickInput
@onready var address_input: LineEdit = $Menu/MainContainer/MainMenu/Option3/AddressInput
@onready var players_container: Node3D = $PlayersContainer
@onready var weapons_container: Node3D = null  # Will be created if doesn't exist
@onready var menu: Control = $Menu
@onready var main_menu: VBoxContainer = $Menu/MainContainer/MainMenu
@export var player_scene: PackedScene

# Weapon spawning counter (server-side only)
var _weapon_spawn_counter: int = 0

# multiplayer chat
@onready var message: LineEdit = $MultiplayerChat/VBoxContainer/HBoxContainer/Message
@onready var send: Button = $MultiplayerChat/VBoxContainer/HBoxContainer/Send
@onready var chat: TextEdit = $MultiplayerChat/VBoxContainer/Chat
@onready var multiplayer_chat: Control = $MultiplayerChat

var chat_visible = false

func _ready():
	multiplayer_chat.hide()
	menu.show()
	multiplayer_chat.set_process_input(true)

	# Add quick-fill preset buttons
	_create_preset_buttons()

	# Create or find weapons container
	if has_node("WeaponsContainer"):
		weapons_container = get_node("WeaponsContainer")
	else:
		weapons_container = Node3D.new()
		weapons_container.name = "WeaponsContainer"
		add_child(weapons_container)
		print("Created WeaponsContainer")

	if not multiplayer.is_server():
		return

	Network.connect("player_connected", Callable(self, "_on_player_connected"))
	multiplayer.peer_disconnected.connect(_remove_player)

	# Spawn initial weapons when server starts
	_spawn_initial_weapons()

func _spawn_initial_weapons():
	if not multiplayer.is_server():
		return

	# Wait a frame for everything to be ready
	await get_tree().process_frame

	# Spawn a sword
	_weapon_spawn_counter += 1
	rpc("spawn_world_weapon",
		"res://level/resources/weapon_sword.tres",
		Vector3(5, 1, 0),
		Vector3.ZERO,
		_weapon_spawn_counter
	)

	# Spawn a shield
	_weapon_spawn_counter += 1
	rpc("spawn_world_weapon",
		"res://level/resources/weapon_shield.tres",
		Vector3(-5, 1, 0),
		Vector3.ZERO,
		_weapon_spawn_counter
	)

func _on_player_connected(peer_id, player_info):
	# for id in Network.players.keys():
	# 	var player_data = Network.players[id]
		# if id != peer_id:
			# rpc_id(peer_id, "sync_player_skin", id, player_data["skin"])

	_add_player(peer_id, player_info)

func _on_host_pressed():
	menu.hide()
	Network.start_host(nick_input.text.strip_edges(), skin_input.text.strip_edges().to_lower())

func _on_join_pressed():
	menu.hide()
	Network.join_game(nick_input.text.strip_edges(), skin_input.text.strip_edges().to_lower(), address_input.text.strip_edges())

func _add_player(id: int, player_info : Dictionary):
	if players_container.has_node(str(id)):
		return
	var player = player_scene.instantiate()
	player.name = str(id)
	player.position = get_spawn_point()
	players_container.add_child(player, true)

	var nick = Network.players[id]["nick"]
	player.nickname.text = nick
	# player.rpc("change_nick", nick)

	var skin_enum = player_info["skin"]
	player.set_player_skin(skin_enum)
	# rpc("sync_player_skin", id, skin_enum)

	# rpc("sync_player_position", id, player.position)

func get_spawn_point() -> Vector3:
	var spawn_point = Vector2.from_angle(randf() * 2 * PI) * 10 # spawn radius
	return Vector3(spawn_point.x, 0, spawn_point.y)

func _remove_player(id):
	if not multiplayer.is_server() or not players_container.has_node(str(id)):
		return
	var player_node = players_container.get_node(str(id))
	if player_node:
		player_node.queue_free()

# @rpc("any_peer", "call_local")
# func sync_player_position(id: int, new_position: Vector3):
# 	var player = players_container.get_node(str(id))
# 	if player:
# 		player.position = new_position

# @rpc("any_peer", "call_local")
# func sync_player_skin(id: int, skin_color: Character.SkinColor):
# 	var player = players_container.get_node(str(id))
# 	if player:
# 		player.set_player_skin(skin_color)

func _on_quit_pressed() -> void:
	get_tree().quit()

# ---------- MULTIPLAYER CHAT ----------
func toggle_chat():
	if menu.visible:
		return

	chat_visible = !chat_visible
	if chat_visible:
		multiplayer_chat.show()
		message.grab_focus()
	else:
		multiplayer_chat.hide()
		get_viewport().set_input_as_handled()

func is_chat_visible() -> bool:
	return chat_visible

func _input(event):
	if event.is_action_pressed("toggle_chat"):
		toggle_chat()
	elif event is InputEventKey and event.keycode == KEY_ENTER:
		_on_send_pressed()

func _on_send_pressed() -> void:
	var trimmed_message = message.text.strip_edges()
	if trimmed_message == "":
		return # do not send empty messages

	var nick = Network.players[multiplayer.get_unique_id()]["nick"]

	rpc("msg_rpc", nick, trimmed_message)
	message.text = ""
	message.grab_focus()

@rpc("any_peer", "call_local")
func msg_rpc(nick, msg):
	chat.text += str(nick, " : ", msg, "\n")

# ---------- PRESET BUTTONS ----------
func _create_preset_buttons():
	# Create a container for preset buttons
	var preset_container = HBoxContainer.new()
	preset_container.name = "PresetContainer"

	var preset_label = Label.new()
	preset_label.text = "Quick Fill:"
	preset_container.add_child(preset_label)

	# Scott button
	var scott_button = Button.new()
	scott_button.text = "Scott"
	scott_button.pressed.connect(_on_scott_preset)
	preset_container.add_child(scott_button)

	# Jemz button
	var jemz_button = Button.new()
	jemz_button.text = "Jemz"
	jemz_button.pressed.connect(_on_jemz_preset)
	preset_container.add_child(jemz_button)

	# Add to main menu at the top
	main_menu.add_child(preset_container)
	main_menu.move_child(preset_container, 0)

func _on_scott_preset():
	nick_input.text = "Scott"
	skin_input.text = "Blue"
	address_input.text = "127.0.0.1"

func _on_jemz_preset():
	nick_input.text = "Jemz"
	skin_input.text = "Red"
	address_input.text = "127.0.0.1"

# ---------- WEAPON SPAWNING ----------
## Spawn a weapon in the world (called from server, syncs to all clients)
@rpc("authority", "call_local", "reliable")
func spawn_world_weapon(weapon_data_path: String, spawn_position: Vector3, initial_velocity: Vector3, weapon_id: int):
	if not weapons_container:
		push_error("WeaponsContainer not found in level!")
		return

	# Load the weapon data resource
	var weapon_data = load(weapon_data_path) as WeaponData
	if not weapon_data:
		push_error("Failed to load weapon data from: " + weapon_data_path)
		return

	# Create WorldWeapon instance
	var world_weapon = WorldWeapon.new()
	world_weapon.weapon_data = weapon_data
	world_weapon.name = "WorldWeapon_" + str(weapon_id)  # Deterministic name
	world_weapon.position = spawn_position

	# Add to weapons container
	weapons_container.add_child(world_weapon, true)

	print("Spawned weapon: ", world_weapon.name, " at ", spawn_position)

	# Apply velocity after physics is ready
	if initial_velocity != Vector3.ZERO:
		await get_tree().process_frame
		world_weapon.linear_velocity = initial_velocity
