HT.Keybinds = {}

-- Direct key polling. The BLT keybind system wasn't reliably binding our default
-- keys, so we poll the keyboard ourselves every frame (edge-detected) and run the
-- action. This works regardless of BLT/SuperBLT version or save state.
HT.Keybinds._down = {}

HT.Keybinds.bindings = {
    { key = "f1", action = function()
        HT:openMenu()
    end },
    { key = "f2", action = function()
        if not HT:isInHeist() then return end
        local val = not (HT:getSetting("enable_god_mode") == true)
        HT.Dexterity:setGodMode(val, true)
        HT:setSetting("enable_god_mode", val)
        HT:setMenuToggle("ut_item_dexterity_toggle_god_mode", val)
    end },
    { key = "f3", action = function()
        if not HT:isInHeist() then return end
        if not HT:isHost() then return end
        HT.Mission:spawnBagOfCurrentType()
    end },
    { key = "f4", action = function()
        if not HT:isInHeist() then return end
        local val = not HT.Dexterity.enableNoclip
        HT.Dexterity:setNoclip(val, false, true)
        HT:setMenuToggle("ut_item_dexterity_toggle_noclip", val)
    end },
    { key = "f5", action = function()
        HT.Reset:all(false)
    end },
    { key = "f6", action = function()
        if HexStatus then HexStatus:toggleVisibility() end
    end },
    { key = "f7", action = function()
        if HT.Extra and HT.Extra.secureAllLoot then HT.Extra:secureAllLoot() end
    end },
    { key = "h", action = function()
        if HT:isInMenu() then return end
        if not HT:isInHeist() then return end
        HT.Keybinds:teleport()
    end },
    { key = "right alt", action = function()
        if HT:isInMenu() then return end
        if not HT:isInHeist() then return end
        HT.Keybinds:replenish()
    end },
}

function HT.Keybinds:isTyping()
    local typing = false
    pcall(function()
        if managers.hud and managers.hud.chat_focus and managers.hud:chat_focus() then
            typing = true
        end
    end)
    return typing
end

-- Called every frame from persist/main.
function HT.Keybinds:poll()
    if not Input then return end
    local keyboard = Input:keyboard()
    if not keyboard then return end
    local typing = HT.Keybinds:isTyping()
    for _, b in ipairs(HT.Keybinds.bindings) do
        local isDown = false
        pcall(function() isDown = keyboard:down(Idstring(b.key)) end)
        if isDown and not HT.Keybinds._down[b.key] and not typing then
            pcall(b.action)
        end
        HT.Keybinds._down[b.key] = isDown
    end
end

function HT.Keybinds:teleport()
    local crosshairRay = HT:getCrosshairRay()

    if not crosshairRay then
        return
    end

    local offset = Vector3()
    mvector3.set(offset, HT:getPlayerCameraForward())
    mvector3.multiply(offset, 100)
    mvector3.add(crosshairRay.hit_position, offset)
    HT:teleportPlayer(crosshairRay.hit_position, HT:getPlayerCameraRotation())
end

function HT.Keybinds:replenish()
    local playerUnit = managers.player:player_unit()

    if not alive(playerUnit) then
        return
    end

    managers.player:add_body_bags_amount(99)
    managers.player:add_special({ name = "cable_tie", amount = 99 })
    managers.player:set_player_state("standard")
    playerUnit:base():replenish()
end
