extends Node

const SND_HIT: AudioStream = preload("res://assets/audio/sfx/hit.wav")
const SND_DEATH: AudioStream = preload("res://assets/audio/sfx/death.wav")
const SND_ABILITY: AudioStream = preload("res://assets/audio/sfx/ability_cast.wav")
const SND_PORTAL: AudioStream = preload("res://assets/audio/sfx/portal_spawn.wav")
const SND_LEVEL: AudioStream = preload("res://assets/audio/sfx/level_up.wav")
const SND_INVASION: AudioStream = preload("res://assets/audio/sfx/invasion_alarm.wav")
const SND_VILLAGE: AudioStream = preload("res://assets/audio/sfx/tavern_damage.wav")
const MUS_TAVERN: AudioStream = preload("res://assets/audio/music/tavern.wav")
const MUS_BATTLE: AudioStream = preload("res://assets/audio/music/battle.wav")
const MUS_INVASION: AudioStream = preload("res://assets/audio/music/invasion.wav")

var music_player: AudioStreamPlayer

func _ready() -> void:
  music_player = AudioStreamPlayer.new()
  music_player.bus = "Master"
  music_player.volume_db = -10.0
  add_child(music_player)
  EventBus.damage_dealt.connect(_on_damage_dealt)
  EventBus.entity_died.connect(_on_died)
  EventBus.ability_used.connect(_on_ability_used)
  EventBus.portal_spawned.connect(_on_portal_spawned)
  EventBus.level_up.connect(_on_level_up)
  EventBus.invasion_started.connect(_on_invasion_started)
  EventBus.village_damaged.connect(_on_village_damaged)
  EventBus.wave_started.connect(_on_wave_started)
  call_deferred("_play_music", MUS_TAVERN)

func _on_damage_dealt(_a: Node, target: Node, _amount: float) -> void:
  _play_at(target, SND_HIT, -8.0)

func _on_died(entity: Node) -> void:
  _play_at(entity, SND_DEATH, -4.0)

func _on_ability_used(player: Node, _i: int, _a: Resource) -> void:
  _play_at(player, SND_ABILITY, -10.0)

func _on_portal_spawned(p: Node) -> void:
  _play_at(p, SND_PORTAL, -4.0)

func _on_level_up(_p: Node, _l: int) -> void:
  _play_global(SND_LEVEL, -4.0)

func _on_invasion_started() -> void:
  _play_global(SND_INVASION, -2.0)
  _play_music(MUS_INVASION)

func _on_village_damaged(_c: float, _m: float) -> void:
  _play_global(SND_VILLAGE, -8.0)

func _on_wave_started(_n: int) -> void:
  _play_music(MUS_BATTLE)

func _play_at(node: Node, stream: AudioStream, vol: float) -> void:
  if not is_instance_valid(node) or not (node is Node3D):
    return
  var p := AudioStreamPlayer3D.new()
  p.stream = stream
  p.volume_db = vol
  p.max_distance = 30.0
  get_tree().current_scene.add_child(p)
  p.global_position = (node as Node3D).global_position
  p.play()
  p.finished.connect(func(): p.queue_free())

func _play_global(stream: AudioStream, vol: float) -> void:
  var p := AudioStreamPlayer.new()
  p.stream = stream
  p.volume_db = vol
  add_child(p)
  p.play()
  p.finished.connect(func(): p.queue_free())

func _play_music(stream: AudioStream) -> void:
  if music_player.stream == stream and music_player.playing:
    return
  music_player.stream = stream
  music_player.play()
