local MT_MISL = freeslot("MT_MISL")

local boomSounds = {
    freeslot("sfx_OFBM1"),
    freeslot("sfx_OFBM2"),
    freeslot("sfx_OFBM3"),
    freeslot("sfx_OFBM4"),
    freeslot("sfx_OFBM5"),
	freeslot("sfx_OFBM6"),
    freeslot("sfx_OFBM7"),
    freeslot("sfx_OFBM8"),
    freeslot("sfx_OFBM9"),
    freeslot("sfx_OFBM10"),
}

----------------------------------------------------
-- FANG-ISH HOMING
----------------------------------------------------
local function GetFangHomingAngle(player)
    local mo = player.mo
    local bestTarget = nil
    local bestDist = 1200 * FRACUNIT

    for moSearch in mobjs.iterate() do
        if moSearch and moSearch.valid and (moSearch.flags & (MF_ENEMY|MF_BOSS)) and moSearch.health > 0 then
            local dist = R_PointToDist2(mo.x, mo.y, moSearch.x, moSearch.y)
            if dist < bestDist then
                local angleToEnemy = R_PointToAngle2(mo.x, mo.y, moSearch.x, moSearch.y)
                local angleDiff = abs(angleToEnemy - mo.angle)
                
                if angleDiff <= ANGLE_45 then
                    bestDist = dist
                    bestTarget = moSearch
                end
            end
        end
    end

    if bestTarget and bestTarget.valid then
        return R_PointToAngle2(mo.x, mo.y, bestTarget.x, bestTarget.y)
    end

    return mo.angle
end

----------------------------------------------------
-- 1. SHOOT VIA SPINSPECIAL
----------------------------------------------------
addHook("SpinSpecial", function(player)
    if not (player.mo and player.mo.valid and player.mo.skin == "janet") then
        return
    end

    local mo = player.mo

    if player.playerstate != PST_LIVE or player.powers[pw_nocontrol] then
        return
    end

    player.pflags = $ & ~(PF_SPINNING|PF_STARTDASH)

    if player.janet_shoot_delay == nil then
        player.janet_shoot_delay = 0
    end

    if player.janet_shoot_delay > 0 then
        return true
    end

    player.janet_shoot_delay = 12 -- Cooldown in tic (~0.3 seconds)

    -- Generate note in front of Janet
    local spawnDist = 28 * FRACUNIT
    local spawnX = mo.x + P_ReturnThrustX(mo, mo.angle, spawnDist)
    local spawnY = mo.y + P_ReturnThrustY(mo, mo.angle, spawnDist)
    local spawnZ = mo.z + (mo.height / 2)

    local proj = P_SpawnMobj(spawnX, spawnY, spawnZ, MT_MISL)
    if proj and proj.valid then
        proj.target = mo
        proj.angle = GetFangHomingAngle(player)
        
        local speed = 90 * FRACUNIT
        proj.momx = P_ReturnThrustX(proj, proj.angle, speed)
        proj.momy = P_ReturnThrustY(proj, proj.angle, speed)
        
        if player.aiming then
            proj.momz = P_ReturnThrustX(proj, player.aiming, speed)
        end

        S_StartSound(mo, sfx_OFPW)
    end

    return true
end)

----------------------------------------------------
-- 2. BUG FIXING
----------------------------------------------------
addHook("PlayerThink", function(player)
    if not (player.mo and player.mo.valid and player.mo.skin == "janet") then
        return
    end

    local mo = player.mo

    -- Shooting cooldown management
    if player.janet_shoot_delay and player.janet_shoot_delay > 0 then
        player.janet_shoot_delay = player.janet_shoot_delay - 1
    end

    -- Buffer removing
    if not ((mo.eflags & MFE_ONGROUND) or P_IsObjectOnGround(mo)) then
        if (player.cmd.buttons & BT_SPIN) then
            if player.janet_shoot_delay and player.janet_shoot_delay > 0 then
                player.cmd.buttons = $ & ~BT_SPIN
            end
        end
    else
        if (player.cmd.buttons & BT_SPIN) or (player.pflags & (PF_SPINNING|PF_STARTDASH)) or mo.state == S_PLAY_ROLL then
            player.cmd.buttons = $ & ~BT_SPIN
            player.pflags = $ & ~(PF_SPINNING|PF_STARTDASH)
            
            if S_SoundPlaying(mo, sfx_spin) then
                S_StopSoundByID(mo, sfx_spin)
            end
            
            if player.speed > (player.normalspeed / 2) then
                mo.state = S_PLAY_RUN
            else
                mo.state = S_PLAY_STND
            end
        end
    end
end)

----------------------------------------------------
-- 3. SFX WHEN AN ENEMY IS DEFEATED (SHOT)
----------------------------------------------------
addHook("MobjDamage", function(target, inflictor, source, damage, damagetype)
    if inflictor and inflictor.type == MT_MISL then
        if (target.flags & (MF_ENEMY|MF_BOSS)) then
            local randomSound = boomSounds[P_RandomRange(1, #boomSounds)]
            S_StartSound(nil, randomSound)
            target.boom_sound_played = true
        end
    end
end)

----------------------------------------------------
-- 4. SFX WHEN AN ENEMY IS DEFEATED
----------------------------------------------------
addHook("MobjDeath", function(target, inflictor, source)
    if (target.flags & (MF_ENEMY|MF_BOSS)) and source and source.player then
        if source.player.mo and source.player.mo.skin == "janet" then
            if not target.boom_sound_played then
                local randomSound = boomSounds[P_RandomRange(1, #boomSounds)]
                S_StartSound(nil, randomSound)
            end
        end
    end
end)