local ____lualib = require("lualib_bundle")
local Map = ____lualib.Map
local __TS__New = ____lualib.__TS__New
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Spread = ____lualib.__TS__Spread
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__Iterator = ____lualib.__TS__Iterator
local __TS__DecorateLegacy = ____lualib.__TS__DecorateLegacy
local ____exports = {}
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local EntityFlag = ____isaac_2Dtypescript_2Ddefinitions.EntityFlag
local ModCallback = ____isaac_2Dtypescript_2Ddefinitions.ModCallback
local ____decorators = require("decorators")
local Exported = ____decorators.Exported
local ____ISCFeature = require("enums.ISCFeature")
local ISCFeature = ____ISCFeature.ISCFeature
local ____ModCallbackCustom = require("enums.ModCallbackCustom")
local ModCallbackCustom = ____ModCallbackCustom.ModCallbackCustom
local ____entities = require("functions.entities")
local spawn = ____entities.spawn
local ____roomData = require("functions.roomData")
local getRoomListIndex = ____roomData.getRoomListIndex
local ____Feature = require("classes.private.Feature")
local Feature = ____Feature.Feature
local v = {
    run = {persistentEntityIndexCounter = 0},
    level = {persistentEntities = __TS__New(Map)},
    room = {spawnedPersistentEntities = __TS__New(Map)}
}
____exports.PersistentEntities = __TS__Class()
local PersistentEntities = ____exports.PersistentEntities
PersistentEntities.name = "PersistentEntities"
__TS__ClassExtends(PersistentEntities, Feature)
function PersistentEntities.prototype.____constructor(self, roomHistory)
    Feature.prototype.____constructor(self)
    self.v = v
    self.postEntityRemove = function(____, entity)
        local ptrHash = GetPtrHash(entity)
        local tuple = v.room.spawnedPersistentEntities:get(ptrHash)
        if tuple == nil then
            return
        end
        local index = tuple[1]
        if self.roomHistory:isLeavingRoom() then
            self:trackDespawningPickupPosition(entity, index)
        else
            self:removePersistentEntity(index, false)
        end
    end
    self.postNewRoomReordered = function()
        local roomListIndex = getRoomListIndex(nil)
        local persistentEntities = {__TS__Spread(v.level.persistentEntities:entries())}
        local persistentEntitiesInThisRoom = __TS__ArrayFilter(
            persistentEntities,
            function(____, ____bindingPattern0)
                local description
                local _index = ____bindingPattern0[1]
                description = ____bindingPattern0[2]
                return roomListIndex == description.roomListIndex
            end
        )
        for ____, ____value in ipairs(persistentEntitiesInThisRoom) do
            local index = ____value[1]
            local description = ____value[2]
            v.level.persistentEntities:delete(index)
            self:spawnAndTrack(
                description.entityType,
                description.variant,
                description.subType,
                description.position,
                index,
                true
            )
        end
    end
    self.featuresUsed = {ISCFeature.ROOM_HISTORY}
    self.callbacksUsed = {{ModCallback.POST_ENTITY_REMOVE, self.postEntityRemove}}
    self.customCallbacksUsed = {{ModCallbackCustom.POST_NEW_ROOM_REORDERED, self.postNewRoomReordered}}
    self.roomHistory = roomHistory
end
function PersistentEntities.prototype.trackDespawningPickupPosition(self, entity, index)
    local previousRoomDescription = self.roomHistory:getLatestRoomDescription()
    if previousRoomDescription == nil then
        return
    end
    local persistentEntityDescription = {
        entityType = entity.Type,
        variant = entity.Variant,
        subType = entity.SubType,
        dimension = previousRoomDescription.dimension,
        roomListIndex = previousRoomDescription.roomListIndex,
        position = entity.Position
    }
    v.level.persistentEntities:set(index, persistentEntityDescription)
end
function PersistentEntities.prototype.spawnAndTrack(self, entityType, variant, subType, position, index, respawning)
    if respawning == nil then
        respawning = false
    end
    local entity = spawn(
        nil,
        entityType,
        variant,
        subType,
        position
    )
    if respawning then
        entity:ClearEntityFlags(EntityFlag.APPEAR)
    end
    local ptrHash = GetPtrHash(entity)
    local tuple = {
        index,
        EntityPtr(entity)
    }
    v.room.spawnedPersistentEntities:set(ptrHash, tuple)
    return entity
end
function PersistentEntities.prototype.removePersistentEntity(self, persistentEntityIndex, removeEntity)
    if removeEntity == nil then
        removeEntity = true
    end
    v.level.persistentEntities:delete(persistentEntityIndex)
    for ____, ____value in __TS__Iterator(v.room.spawnedPersistentEntities) do
        local ptrHash = ____value[1]
        local tuple = ____value[2]
        do
            local index, entityPtr = table.unpack(tuple)
            if index ~= persistentEntityIndex then
                goto __continue16
            end
            v.room.spawnedPersistentEntities:delete(ptrHash)
            if removeEntity and entityPtr.Ref ~= nil then
                entityPtr.Ref:Remove()
            end
        end
        ::__continue16::
    end
end
__TS__DecorateLegacy({Exported}, PersistentEntities.prototype, "removePersistentEntity", true)
function PersistentEntities.prototype.spawnPersistentEntity(self, entityType, variant, subType, position)
    local ____v_run_0, ____persistentEntityIndexCounter_1 = v.run, "persistentEntityIndexCounter"
    ____v_run_0[____persistentEntityIndexCounter_1] = ____v_run_0[____persistentEntityIndexCounter_1] + 1
    local entity = self:spawnAndTrack(
        entityType,
        variant,
        subType,
        position,
        v.run.persistentEntityIndexCounter
    )
    return {entity = entity, persistentIndex = v.run.persistentEntityIndexCounter}
end
__TS__DecorateLegacy({Exported}, PersistentEntities.prototype, "spawnPersistentEntity", true)
return ____exports
