extends Node

const NORMAL_GATES: int = 3
const TIMER_SECONDS: float = 600.0

@onready var spawn_system: Node = get_node("../SpawnSystem")

var timer_remaining: float = TIMER_SECONDS
var red_gate: Node = null
var red_portal_done: bool = false
var active: bool = false

func _ready() -> void:
  EventBus.gate_destroyed.connect(_on_gate_destroyed)
  EventBus.boss_defeated.connect(_on_boss_defeated)
  EventBus.invasion_ended.connect(_on_invasion_ended)

func start_wave(n: int) -> void:
  if not (multiplayer.is_server() or multiplayer.multiplayer_peer == null):
    return
  GameState.current_wave = n
  red_portal_done = false
  red_gate = null
  timer_remaining = TIMER_SECONDS
  active = true
  EventBus.wave_started.emit(n)
  _spawn_initial_gates()

func _spawn_initial_gates() -> void:
  for i in range(NORMAL_GATES):
    var pos := _random_outer_position(20.0, 40.0)
    spawn_system.spawn_gate_at(pos, false)
  red_gate = spawn_system.spawn_gate_at(_random_outer_position(30.0, 45.0), true)

func _random_outer_position(min_d: float, max_d: float) -> Vector3:
  var angle: float = randf() * TAU
  var d: float = randf_range(min_d, max_d)
  return Vector3(cos(angle) * d, 0.5, sin(angle) * d)

func _physics_process(delta: float) -> void:
  if not active:
    return
  if not (multiplayer.is_server() or multiplayer.multiplayer_peer == null):
    return
  timer_remaining = max(0.0, timer_remaining - delta)
  EventBus.wave_timer_tick.emit(timer_remaining)
  if timer_remaining <= 0.0 and not red_portal_done:
    active = false
    EventBus.invasion_started.emit()
    var inv: Node = get_node_or_null("../InvasionSystem")
    if inv and inv.has_method("start"):
      inv.start(GameState.current_wave)

func _on_gate_destroyed(gate: Node) -> void:
  if not (multiplayer.is_server() or multiplayer.multiplayer_peer == null):
    return
  if not gate.is_in_group("red_gate"):
    var pos := _random_outer_position(20.0, 40.0)
    spawn_system.spawn_gate_at(pos, false)

func _on_boss_defeated(_boss: Node) -> void:
  if not (multiplayer.is_server() or multiplayer.multiplayer_peer == null):
    return
  if GameState.dungeon_red and not red_portal_done:
    red_portal_done = true
    active = false
    EventBus.wave_ended.emit(GameState.current_wave, true)
    var t := get_tree().create_timer(2.0)
    t.timeout.connect(func(): start_wave(GameState.current_wave + 1))

func _on_invasion_ended(success: bool) -> void:
  if not (multiplayer.is_server() or multiplayer.multiplayer_peer == null):
    return
  if success:
    EventBus.wave_ended.emit(GameState.current_wave, true)
    var t := get_tree().create_timer(2.0)
    t.timeout.connect(func(): start_wave(GameState.current_wave + 1))
