local ____lualib = require("lualib_bundle")
local __TS__ArrayEvery = ____lualib.__TS__ArrayEvery
local ____exports = {}
local ____string = require("functions.string")
local trimPrefix = ____string.trimPrefix
local ____types = require("functions.types")
local isString = ____types.isString
local isUserdata = ____types.isUserdata
--- Helper function to get the name of a class from the Isaac API. This is contained within the
-- "__type" metatable key.
-- 
-- For example, a `Vector` class is has a name of "Vector".
-- 
-- Returns undefined if the object is not of type `userdata` or if the "__type" metatable key does
-- not exist.
-- 
-- In some cases, Isaac classes can be a read-only. If this is the case, the "__type" field will be
-- prepended with "const ". This function will always strip this prefix, if it exists. For example,
-- the class name returned for "const Vector" will be "Vector".
function ____exports.getIsaacAPIClassName(self, object)
    if not isUserdata(nil, object) then
        return nil
    end
    local metatable = getmetatable(object)
    if metatable == nil then
        return nil
    end
    local classType = metatable.__type
    if not isString(nil, classType) then
        return nil
    end
    return trimPrefix(nil, classType, "const ")
end
--- Helper function to detect if a variable is of type `EntityBomb`.
function ____exports.isBomb(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityBomb"
end
--- Helper function to detect if a variable is of type `GridEntityDoor`.
function ____exports.isDoor(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntityDoor"
end
--- Helper function to detect if a variable is of type `EntityEffect`.
function ____exports.isEffect(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityEffect"
end
--- Helper function to detect if a variable is of type `Entity`. This will return false for child
-- classes such as `EntityPlayer` or `EntityTear`.
function ____exports.isEntity(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "Entity"
end
--- Helper function to detect if a variable is of type `EntityFamiliar`.
function ____exports.isFamiliar(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityEffect"
end
--- Helper function to detect if a variable is of type `GridEntity`.
function ____exports.isGridEntity(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntity"
end
--- Helper function to check if something is an instantiated class from the Isaac API. (All classes
-- from the Isaac API have a type of "userdata" in Lua with a metatable key of "__type" equal to the
-- name of the class.)
function ____exports.isIsaacAPIClass(self, object)
    local isaacAPIClassType = ____exports.getIsaacAPIClassName(nil, object)
    return isaacAPIClassType ~= nil
end
function ____exports.isIsaacAPIClassOfType(self, object, classType)
    local isaacAPIClassType = ____exports.getIsaacAPIClassName(nil, object)
    return isaacAPIClassType == classType or isaacAPIClassType == "const " .. classType
end
--- Helper function to detect if a variable is of type `EntityKnife`.
function ____exports.isKnife(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityKnife"
end
--- Helper function to detect if a variable is of type `EntityLaser`.
function ____exports.isLaser(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityLaser"
end
--- Helper function to detect if a variable is of type `EntityNPC`.
function ____exports.isNPC(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityNPC"
end
--- Helper function to detect if a variable is of type `EntityPickup`.
function ____exports.isPickup(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityPickup"
end
--- Helper function to detect if a variable is of type `GridEntityPit`.
function ____exports.isPit(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntityPit"
end
--- Helper function to detect if a variable is of type `EntityPlayer`.
function ____exports.isPlayer(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityPlayer"
end
--- Helper function to detect if a variable is of type `GridEntityPoop`.
function ____exports.isPoop(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntityPoop"
end
--- Helper function to detect if a variable is of type `GridEntityPressurePlate`.
function ____exports.isPressurePlate(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntityPressurePlate"
end
--- Helper function to detect if a variable is of type `EntityProjectile`.
function ____exports.isProjectile(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityProjectile"
end
--- Helper function to detect if a variable is of type `GridEntityRock`.
function ____exports.isRock(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntityRock"
end
--- Helper function to detect if a variable is of type `GridEntitySpikes`.
function ____exports.isSpikes(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntitySpikes"
end
--- Helper function to detect if a variable is of type `GridEntityTNT`.
function ____exports.isTNT(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "GridEntityTNT"
end
--- Helper function to detect if a variable is of type `EntityTear`.
function ____exports.isTear(self, variable)
    return ____exports.getIsaacAPIClassName(nil, variable) == "EntityTear"
end
--- Helper function to check if an instantiated Isaac API class is equal to another one of the same
-- type. You must provide the list of keys to check for.
function ____exports.isaacAPIClassEquals(self, object1, object2, keys)
    local table1 = object1
    local table2 = object2
    return __TS__ArrayEvery(
        keys,
        function(____, key) return table1[key] == table2[key] end
    )
end
return ____exports
