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

local function superBounceNail()
    if puppet.BossHitCooldown <= 0 then
        celeste.Mod.Kelper.Mechanics.Nail.NailRebound(2)
        celeste.Mod.Kelper.Mechanics.Nail.ConsumeSwing()
        player:Play("event:/game/06_reflection/feather_bubble_bounce") --Play bounce sound
        resetHitCooldown()
    end
    return true
end

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

local function switchNailColliders()
    local vulnerable = false
    local circleNailCollider = createNailCollider(superBounceNail)
    local hurtNailCollider = createNailCollider(takeDamage)
    addComponentToBoss(circleNailCollider)
    setFlag("uumuu_change_vulnerable", false)
    while true do
        if getFlag("uumuu_change_vulnerable") then
            vulnerable = not vulnerable
            if vulnerable then
                changeBaseHitboxTo("vulnerable")
                addComponentToBoss(hurtNailCollider)
                circleNailCollider:RemoveSelf()
            else
                changeBaseHitboxTo("main")
                addComponentToBoss(circleNailCollider)
                hurtNailCollider:RemoveSelf()
            end
            setFlag("uumuu_change_vulnerable", false)
        end
        wait()
    end
end

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

    disableCollisions()

    setFlag("uumuu_slow", true)
    while not getFlag("uumuu_static") do wait() end

    interruptPattern()
    startNextAttackPattern()
end

local function v2L(vector)
    return math.sqrt(vector.X * vector.X + vector.Y * vector.Y)
end

local function normalize(vector, length)
    local len = v2L(vector)
    if length <= 0 then return vector2(0, 0) end

    if len == 0 then return vector end
    return vector2(vector.X / len, vector.Y / len) * (length or 1)
end

local function passiveFollowPlayer()
    setFlag("uumuu_follower", false)
    setFlag("uumuu_static", true)
    setFlag("uumuu_slow", false)
    
    local count = 5
    local delay = 0.1

    local looped = false
    local readIndex = 1
    local saveIndex = 1
    local playerPositions = {n=count}
    for i = 1, count, 1 do playerPositions[i] = player.Position end

    while true do
        local newPos = vector2(player.Position.X, player.Position.Y - 16)
        playerPositions[saveIndex] = newPos
        if saveIndex >= count then looped = true end
        saveIndex = (saveIndex % count) + 1
        if looped then readIndex = saveIndex end

        local following = getFlag("uumuu_follower")
        local speedLen = v2L(puppet.Speed)
        if following then
            setFlag("uumuu_static", false)
            local slow = getFlag("uumuu_slow")

            if not slow and speedLen < 80 then speedLen = speedLen + 10
            elseif slow and speedLen > 0 then speedLen = speedLen - 10 end

            local dir = normalize(playerPositions[readIndex] - puppet.Position, speedLen)
            speedTweenTo(dir.X, dir.Y, delay)
        end

        wait(delay)

        if following and v2L(puppet.Speed) == 0 then
            setFlag("uumuu_follower", false)
            setFlag("uumuu_static", true)
        end
    end
end

function setup()
    addConstantBackgroundCoroutine(switchNailColliders)
    addConstantBackgroundCoroutine(healthTracking)
    addConstantBackgroundCoroutine(passiveFollowPlayer)
end