local world = require("world")
local band = bit.band

local collidingEntities = world:filteredSystem("collidingEntitites", {
    position = T.XyPair,
    size = T.XyPair,
    canCollideWith = T.BitMask,
    isSolid = Maybe(T.bool),
})

local function intersects(rect, rectOther)
    local left = rect.position.x
    local right = rect.position.x + rect.size.x
    local top = rect.position.y
    local bottom = rect.position.y + rect.size.y

    local leftOther = rectOther.position.x
    local rightOther = rectOther.position.x + rectOther.size.x
    local topOther = rectOther.position.y
    local bottomOther = rectOther.position.y + rectOther.size.y

    return leftOther < right and left < rightOther and topOther < bottom and top < bottomOther
end

world:filteredSystem(
    "collisionDetection",
    { position = T.XyPair, size = T.XyPair, canBeCollidedBy = T.BitMask, isSolid = Maybe(T.bool) },
    -- Here, the entity, e, refers to some entity that a moving object may be colliding *into*
    function(e, _, system)
        for _, collider in pairs(collidingEntities.entities) do
            if
                (e ~= collider)
                and collider.canCollideWith
                and e.canBeCollidedBy
                and band(collider.canCollideWith, e.canBeCollidedBy) ~= 0
                and intersects(e, collider)
            then
                system.world:addEntity({
                    collisionBetween = { collider = collider, collidedInto = e },
                })
            end
        end
    end
)