extends Node

const SFX_PATHS := {
  "hit": "res://assets/audio/sfx/hit.wav",
  "death": "res://assets/audio/sfx/death.wav",
  "level_up": "res://assets/audio/sfx/level_up.wav",
  "ability_cast": "res://assets/audio/sfx/ability_cast.wav",
  "portal_spawn": "res://assets/audio/sfx/portal_spawn.wav",
  "invasion_alarm": "res://assets/audio/sfx/invasion_alarm.wav",
  "tavern_damage": "res://assets/audio/sfx/tavern_damage.wav",
}

const MUSIC_PATHS := {
  "tavern": "res://assets/audio/music/tavern.wav",
  "battle": "res://assets/audio/music/battle.wav",
  "invasion": "res://assets/audio/music/invasion.wav",
}

const SFX_POOL_SIZE := 8

var sfx_cache: Dictionary = {}
var music_cache: Dictionary = {}
var sfx_players: Array[AudioStreamPlayer] = []
var music_player: AudioStreamPlayer = null
var current_music: String = ""

func _ready() -> void:
  for i in range(SFX_POOL_SIZE):
    var p := AudioStreamPlayer.new()
    p.volume_db = -6.0
    add_child(p)
    sfx_players.append(p)
  music_player = AudioStreamPlayer.new()
  music_player.volume_db = -12.0
  music_player.finished.connect(_on_music_finished)
  add_child(music_player)
  _preload_audio()
  EventBus.attack_executed.connect(_on_attack_executed)
  EventBus.entity_died.connect(_on_entity_died)
  EventBus.level_up.connect(_on_level_up)
  EventBus.portal_spawn.connect(_on_portal_spawn)
  EventBus.tavern_damaged.connect(_on_tavern_damaged)
  EventBus.invasion_started.connect(_on_invasion_started)
  EventBus.invasion_ended.connect(_on_invasion_ended)
  EventBus.wave_started.connect(_on_wave_started)
  _play_music("tavern")

func _preload_audio() -> void:
  for key in SFX_PATHS:
    var path: String = SFX_PATHS[key]
    if ResourceLoader.exists(path):
      var stream: AudioStream = load(path)
      if stream:
        sfx_cache[key] = stream
  for key in MUSIC_PATHS:
    var path: String = MUSIC_PATHS[key]
    if ResourceLoader.exists(path):
      var stream: AudioStream = load(path)
      if stream is AudioStreamWAV:
        (stream as AudioStreamWAV).loop_mode = AudioStreamWAV.LOOP_FORWARD
        (stream as AudioStreamWAV).loop_end = (stream as AudioStreamWAV).data.size() / 2
      if stream:
        music_cache[key] = stream

func play_sfx(key: String) -> void:
  if not sfx_cache.has(key):
    return
  for p in sfx_players:
    if not p.playing:
      p.stream = sfx_cache[key]
      p.play()
      return

func _play_music(key: String) -> void:
  if current_music == key and music_player.playing:
    return
  if not music_cache.has(key):
    return
  music_player.stream = music_cache[key]
  music_player.play()
  current_music = key

func _on_music_finished() -> void:
  if current_music != "" and music_cache.has(current_music):
    music_player.play()

func _on_attack_executed(_attacker, _pos, _dir, _dmg) -> void:
  play_sfx("hit")

func _on_entity_died(entity: Node) -> void:
  if entity == PlayerData:
    return
  play_sfx("death")

func _on_level_up(_player, _level) -> void:
  play_sfx("level_up")

func _on_portal_spawn(_portal, _enemies) -> void:
  play_sfx("portal_spawn")

func _on_tavern_damaged(_current, _max_val) -> void:
  play_sfx("tavern_damage")

func _on_invasion_started(_enemies) -> void:
  play_sfx("invasion_alarm")
  _play_music("invasion")

func _on_invasion_ended(_success) -> void:
  _play_music("battle")

func _on_wave_started(_wave) -> void:
  if current_music != "invasion":
    _play_music("battle")
