extends Node

const ENEMY_SCENE: PackedScene = preload("res://scenes/entities/enemy/enemy.tscn")
const PORTAL_SCENE: PackedScene = preload("res://scenes/entities/portal/portal.tscn")
const GATE_SCENE: PackedScene = preload("res://scenes/entities/gate/gate.tscn")

func _enemy_root() -> Node3D:
  var n: Node = get_node_or_null("/root/World/EntityRoot/Enemies")
  if n == null:
    n = get_node_or_null("/root/Dungeon/EntityRoot/Enemies")
  return n

func _portal_root() -> Node3D:
  var n: Node = get_node_or_null("/root/World/EntityRoot/Portals")
  if n == null:
    n = get_node_or_null("/root/Dungeon/EntityRoot/Portals")
  return n

func _gate_root() -> Node3D:
  var n: Node = get_node_or_null("/root/World/EntityRoot/Gates")
  if n == null:
    n = get_node_or_null("/root/Dungeon/EntityRoot/Gates")
  return n

func spawn_enemy_at(pos: Vector3, strong: bool = false, mult: float = 1.0) -> Node:
  if not multiplayer.is_server() and multiplayer.multiplayer_peer != null:
    return null
  var root := _enemy_root()
  if root == null:
    return null
  var e: CharacterBody3D = ENEMY_SCENE.instantiate()
  var stats := EnemyStats.new()
  var s: float = mult * (3.0 if strong else 1.0)
  stats.max_health = 30.0 * s
  stats.attack_damage = 5.0 * s
  stats.attack_range = 2.0
  stats.attack_cooldown = 1.5
  stats.speed = 3.0
  stats.aggro_radius = 12.0
  stats.xp_value = 5.0 * s
  e.stats_resource = stats
  e.name = "Enemy_%d" % (Time.get_ticks_msec() + randi() % 1000)
  root.add_child(e, true)
  e.global_position = pos
  return e

func spawn_boss_at(pos: Vector3, mult: float = 1.0) -> Node:
  if not multiplayer.is_server() and multiplayer.multiplayer_peer != null:
    return null
  var root := _enemy_root()
  if root == null:
    return null
  var b: CharacterBody3D = ENEMY_SCENE.instantiate()
  b.is_boss = true
  var stats := BossStats.new()
  stats.max_health = 250.0 * mult
  stats.attack_damage = 12.0 * mult
  stats.attack_range = 3.0
  stats.attack_cooldown = 1.6
  stats.speed = 3.5
  stats.xp_value = 100.0 * mult
  b.stats_resource = stats
  b.name = "Boss_%d" % Time.get_ticks_msec()
  root.add_child(b, true)
  b.global_position = pos
  return b

func spawn_portal_at(pos: Vector3, is_red: bool) -> Node:
  if not multiplayer.is_server() and multiplayer.multiplayer_peer != null:
    return null
  var root := _portal_root()
  if root == null:
    return null
  var p: StaticBody3D = PORTAL_SCENE.instantiate()
  p.is_red = is_red
  p.name = "Portal_%d" % Time.get_ticks_msec()
  root.add_child(p, true)
  p.global_position = pos
  EventBus.portal_spawned.emit(p)
  return p

func spawn_gate_at(pos: Vector3, is_red: bool) -> Node:
  if not multiplayer.is_server() and multiplayer.multiplayer_peer != null:
    return null
  var root := _gate_root()
  if root == null:
    return null
  var g: StaticBody3D = GATE_SCENE.instantiate()
  g.is_red = is_red
  g.name = "Gate_%s_%d" % ["red" if is_red else "n", Time.get_ticks_msec() + randi() % 1000]
  root.add_child(g, true)
  g.global_position = pos
  return g
