extends Node

var Skellie = preload("res://src/Skellie.gd")
var Bat = preload("res://src/Bat.gd")
var Zombie = preload("res://src/Zombie.gd")
var Lamb = preload("res://src/Lamb.gd")

var skeletons = []
var bats = []
var zombies = []
var coolStart = 8.0
var coolEnd = 4.5
var minCooldown
var maxCooldown
var cooldown = 0.0
var perSheep = 2
var pSheep
var pRest

# relative monster chances
var qSkel1 = 1.0
var qSkel2 = 0.2
var qZomb1 = 0.0
var qZomb2 = 0.4
var qBat1 = 0.0
var qBat2 = 0.4
var qSkel
var qZomb
var qBat
var qTotal

var nSpawns = 0
var spawning = false

var world

var zombiePlayer
var sounds_zombie = []
var batPlayer
var sounds_bat = []
var sheepPlayer = []
var sounds_sheep = []


func _ready():
  world = $"/root/World/ys"
  zombiePlayer = AudioStreamPlayer.new()
  self.add_child(zombiePlayer)
  for idx in range(4):
    sounds_zombie.append(load("res://sound/zombie-" + str(idx) + ".wav"))
  batPlayer = AudioStreamPlayer.new()
  self.add_child(batPlayer)
  for idx in range(1):
    sounds_bat.append(load("res://sound/bat-" + str(idx) + ".wav"))
  sheepPlayer = AudioStreamPlayer.new()
  self.add_child(sheepPlayer)
  for idx in range(1):
    sounds_sheep.append(load("res://sound/sheep-" + str(idx) + ".wav"))
    

func _process(delta):
  cooldown -= delta
  
  if get_tree().get_nodes_in_group("enemies").size() + get_tree().get_nodes_in_group("lambs").size() == 0:
    
    cooldown = 0
  
  if cooldown <= 0:
    if not spawning: # start spawning
      spawning = true
      # adjust difficulty
      var winCount = $"/root/World".winCount
      var player = $"/root/World/ys/player"   
      var level = player.lambs + player.mutton - 5.0 # important .0 for float
      # hardest frequency achieved at 45 sheep
      minCooldown = max(0.0, coolStart - 1.0 + (coolEnd - coolStart) * (level / winCount))
      maxCooldown = max(1.0, coolStart + 1.0 + (coolEnd - coolStart) * (level / winCount))
      # 1 sheep should get you between 1 and 3 kills
      perSheep = 1.0 + 2.0 * level / winCount
      pSheep = 1.0 / (perSheep + 1.0)
      pRest = 1.0 - pSheep
      qSkel = qSkel1 + (level / winCount) * (qSkel2 - qSkel1)
      qZomb = qZomb1 + (max(0, (level - 2)) / winCount) * (qZomb2 - qZomb1)
      qBat = qBat1 + (max(0, (level - 5)) / winCount) * (qBat2 - qBat1)
      qTotal = qSkel + qZomb + qBat
      nSpawns = 2.0 + floor((level / winCount) * 3.0)
    
    # if number of spawns > 50, wait until some disappear.
    if get_tree().get_nodes_in_group("enemies").size() + get_tree().get_nodes_in_group("sheep").size() < 50:
      if nSpawns >= 0:
        nSpawns -= 1
        cooldown = 0.5 # wait until the next spawn
        var side = _pickSide()
        var monsterRoll = randf()
        if monsterRoll < pSheep:
          spawnLamb(side)
        elif monsterRoll < pSheep + pRest * (qSkel / qTotal):
          spawnSkellie(side)
        elif monsterRoll < pSheep + pRest * (qSkel + qZomb) / qTotal:
          spawnZombie(side)
        elif monsterRoll < pSheep + pRest * (qSkel + qZomb + qBat) / qTotal:
          spawnBat(side)
        else:
          print("No monster?")
      else:
        spawning = false
        cooldown = minCooldown + randf() * (maxCooldown - minCooldown)

      
func _pickSide():
  var side = Vector2()
  while side.x == 0 and side.y == 0:
    side.x = randi() % 3 - 1
    side.y = randi() % 3 - 1
  return side
  
func spawnSkellie(side):
  world.add_child(Skellie.new(side))
  
func spawnZombie(side):
  world.add_child(Zombie.new(side))
  if not zombiePlayer.is_playing():
    zombiePlayer.set_volume_db(-23.0)
    zombiePlayer.stream = sounds_zombie[randi() % sounds_zombie.size()]
    zombiePlayer.play()

func spawnBat(side):
  world.add_child(Bat.new(side))
  if not batPlayer.is_playing():
    batPlayer.set_volume_db(-23.0)
    batPlayer.stream = sounds_bat[randi() % sounds_bat.size()]
    batPlayer.play()

func spawnLamb(side):
  world.add_child(Lamb.new(side))
  if not sheepPlayer.is_playing():
    sheepPlayer.set_volume_db(-23.0)
    sheepPlayer.stream = sounds_sheep[randi() % sounds_sheep.size()]
    sheepPlayer.play()
  