local function createNailCollider(func, collider)
  return celeste.Mod.CrossoverCollab.CrossoverCollabModule.CreateNailColliderDelegate(func, collider)
end

local function rebound()
  if puppet.BossHitCooldown <= 0 then
    celeste.Mod.Kelper.Mechanics.Nail.NailRebound(1.75)
    celeste.Mod.Kelper.Mechanics.Nail.ConsumeSwing()
    player:Play("event:/CC/CC_HollowKnight/SFX/Boss SFX/Parry") --Play parry/spikes sound
    resetHitCooldown()
  end
  return true
end

local function hurt()
  if puppet.BossHitCooldown <= 0 then
    celeste.Mod.Kelper.Mechanics.Nail.NailRebound(0.5)
    boss:DecreaseHealth()
    resetHitCooldown()
    player:Play("event:/CC/CC_HollowKnight/SFX/Boss SFX/Damage") --Play hit/squish sound
  end
  return true
end

local function switchNailColliders()
  local knightNum = tonumber(string.sub(bossID, -1))

  local vulnerable = true
  local spin_nail_collider = createNailCollider(rebound)
  local standing_nail_collider = createNailCollider(hurt)
  local knightFlag = "change_watcher_" .. knightNum

  addComponentToBoss(standing_nail_collider)
  setFlag(knightFlag, false)
  while true do
    if getFlag(knightFlag) then
      vulnerable = not vulnerable
      if vulnerable then
        addComponentToBoss(standing_nail_collider)
        spin_nail_collider:RemoveSelf()
      else
        addComponentToBoss(spin_nail_collider)
        standing_nail_collider:RemoveSelf()
      end
      setFlag(knightFlag, false)
    end
    wait()
  end
end

local function lookForPlayer()
  local knightNum = tonumber(string.sub(bossID, -1))
  local knightFlag = "turn_" .. knightNum
  while true do
    if getFlag(knightFlag) then
      if (player.Position.X - puppet.Position.X) * puppet.Facing < 0 then
        wait(0.25)
        puppet.Facing = puppet.Facing * -1
        wait(0.25)
      end
      setFlag(knightFlag, false)
    end
    wait()
  end
end

local function healthTracking()
  while getHealth() > 0 do
    wait()
  end

  disableCollisions()

  interruptPattern()
  startNextAttackPattern()
end

local function fightInit()
  local knightNum = tonumber(string.sub(bossID, -1))
  local awakeFlag = "awake_knight_" .. knightNum
  local dieFlag = "kill_watcher_" .. knightNum

  for i = 1, 6, 1 do
    setFlag("kill_watcher_" .. i, false)
  end

  setFlag("WatcherExitGate", false)
  setFlag(dieFlag, false)
  setFlag(awakeFlag, false)
  if (knightNum == 1) then
    while not getFlag("WatcherStart") do
      wait()
    end
    wait()
    setFlag("WatcherStart", false)
  elseif knightNum == 2 or knightNum == 3 then
    while not getFlag("kill_watcher_1") do
      wait()
    end
  elseif knightNum == 6 then
    while not getFlag("kill_watcher_4") and not getFlag("kill_watcher_5") do --6 waits on 4 or 5
      wait()
    end
  else
    while not getFlag("kill_watcher_" .. (knightNum - 2)) do --4 waits on 2, 5 on 3
      wait()
    end
  end
  setFlag(awakeFlag, true)
end

local function endFight()
  local knightNum = tonumber(string.sub(bossID, -1))
  setFlag("all_knights_dead", false)
  if knightNum == 6 then
    local first = false
    local second = false
    local third = false
    local fourth = false
    local fifth = false
    local sixth = false

    while not first or not second or not third or not fourth or not fifth or not sixth do
      if not first then
        first = getFlag("kill_watcher_1")
        setFlag("kill_watcher_1", first)
      end
      if not second then
        second = getFlag("kill_watcher_2")
        setFlag("kill_watcher_2", second)
      end
      if not third then
        third = getFlag("kill_watcher_3")
        setFlag("kill_watcher_3", third)
      end
      if not fourth then
        fourth = getFlag("kill_watcher_4")
        setFlag("kill_watcher_4", fourth)
      end
      if not fifth then
        fifth = getFlag("kill_watcher_5")
        setFlag("kill_watcher_5", fifth)
      end
      if not sixth then
        sixth = getFlag("kill_watcher_6")
        setFlag("kill_watcher_6", sixth)
      end
      wait()
    end
	playSound("event:/CC/CC_HollowKnight/SFX/Boss SFX/BossExplode")
    setFlag("all_knights_dead", true)
    setFlag("WatcherEntranceGate", false)
    setFlag("WatcherExitGate", true)
  end
end

function setup()
  addConstantBackgroundCoroutine(healthTracking)
  addConstantBackgroundCoroutine(switchNailColliders)
  addConstantBackgroundCoroutine(fightInit)
  addConstantBackgroundCoroutine(lookForPlayer)
  addConstantBackgroundCoroutine(endFight)
end