-- ~/.hammerspoon/bump.lua

local bump = {}

-- Persistence and State
_G.BumpState = _G.BumpState or {
    gridSize = "3x2", -- 3 columns, 2 rows
    enabled = true
}

-- Cleanup existing resources
if _G.BumpResources then
    for _, item in ipairs(_G.BumpResources) do
        if item.stop then item:stop() end
        if item.delete then item:delete() end
    end
end
_G.BumpResources = {}

-- ~~~~~~~~~~ MANUAL BUMP LOGIC ~~~~~~~~~~
local bentoWatcher = hs.window.filter.new()

bentoWatcher:subscribe(hs.window.filter.windowMoved, function(newWin)
    if not _G.BumpState.enabled then return end
    
    local f1 = newWin:frame()
    local screen = newWin:screen()
    local maxW = screen:frame().w
    local allWindows = hs.window.visibleWindows()

    -- Calculate how wide one "slot" is (e.g., 1/3 of screen)
    local cols = tonumber(_G.BumpState.gridSize:sub(1,1))
    local slotWidth = maxW / cols

    for _, oldWin in ipairs(allWindows) do
        if oldWin:id() ~= newWin:id() and oldWin:screen() == screen and oldWin:isStandard() then
            local f2 = oldWin:frame()
            
            -- Manual Intersection check
            local dx = math.max(0, math.min(f1.x + f1.w, f2.x + f2.w) - math.max(f1.x, f2.x))
            local dy = math.max(0, math.min(f1.y + f1.h, f2.y + f2.h) - math.max(f1.y, f2.y))
            
            -- If they overlap significantly
            if (dx * dy) > (f1.w * f1.h * 0.4) then
                local newX = f2.x + slotWidth
                
                -- If pushing right stays on screen, move it.
                -- Otherwise, move it to the start of the next row (y + height)
                if (newX + 50) > maxW then
                    oldWin:setFrame({x = 0, y = f2.y + f2.h, w = f2.w, h = f2.h})
                else
                    oldWin:setFrame({x = newX, y = f2.y, w = f2.w, h = f2.h})
                end
                
                hs.alert.show("Bumping " .. oldWin:application():name())
            end
        end
    end
end)
table.insert(_G.BumpResources, bentoWatcher)

-- ~~~~~~~~~~ MENU BAR ~~~~~~~~~~
local menu = hs.menubar.new()
table.insert(_G.BumpResources, menu)

local function updateMenu()
    return {
        { title = "Bump Status: " .. (_G.BumpState.enabled and "ON" or "OFF"), disabled = true },
        { title = "-" },
        { title = "Grid: 2x2", fn = function() _G.BumpState.gridSize = "2x2"; hs.reload() end, checked = (_G.BumpState.gridSize == "2x2") },
        { title = "Grid: 3x2", fn = function() _G.BumpState.gridSize = "3x2"; hs.reload() end, checked = (_G.BumpState.gridSize == "3x2") },
        { title = "-" },
        { title = "Reload Bump Only", fn = function() package.loaded["bump"] = nil; require("bump") end },
        { title = "Hard Reload All", fn = hs.reload }
    }
end

menu:setTitle("⇄")
menu:setMenu(updateMenu)

return bump