local ____lualib = require("lualib_bundle")
local __TS__New = ____lualib.__TS__New
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__DecorateLegacy = ____lualib.__TS__DecorateLegacy
local Map = ____lualib.Map
local __TS__Iterator = ____lualib.__TS__Iterator
local ____exports = {}
local spawnGridEntityForJSONRoom, fixPitGraphics, getPitMap, getPitFrame
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local EntityCollisionClass = ____isaac_2Dtypescript_2Ddefinitions.EntityCollisionClass
local EntityGridCollisionClass = ____isaac_2Dtypescript_2Ddefinitions.EntityGridCollisionClass
local EntityType = ____isaac_2Dtypescript_2Ddefinitions.EntityType
local GridEntityType = ____isaac_2Dtypescript_2Ddefinitions.GridEntityType
local PickupVariant = ____isaac_2Dtypescript_2Ddefinitions.PickupVariant
local PitfallVariant = ____isaac_2Dtypescript_2Ddefinitions.PitfallVariant
local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
local ____cachedEnumValues = require("arrays.cachedEnumValues")
local GRID_ENTITY_XML_TYPE_VALUES = ____cachedEnumValues.GRID_ENTITY_XML_TYPE_VALUES
local ____cachedClasses = require("core.cachedClasses")
local game = ____cachedClasses.game
local ____decorators = require("decorators")
local Exported = ____decorators.Exported
local ____ISCFeature = require("enums.ISCFeature")
local ISCFeature = ____ISCFeature.ISCFeature
local ____emptyRoom = require("functions.emptyRoom")
local emptyRoom = ____emptyRoom.emptyRoom
local ____entities = require("functions.entities")
local getEntityIDFromConstituents = ____entities.getEntityIDFromConstituents
local spawnWithSeed = ____entities.spawnWithSeed
local ____gridEntities = require("functions.gridEntities")
local convertXMLGridEntityType = ____gridEntities.convertXMLGridEntityType
local getGridEntities = ____gridEntities.getGridEntities
local spawnGridEntityWithVariant = ____gridEntities.spawnGridEntityWithVariant
local ____jsonRoom = require("functions.jsonRoom")
local getRandomJSONEntity = ____jsonRoom.getRandomJSONEntity
local ____log = require("functions.log")
local log = ____log.log
local ____rng = require("functions.rng")
local isRNG = ____rng.isRNG
local newRNG = ____rng.newRNG
local ____roomGrid = require("functions.roomGrid")
local gridCoordinatesToWorldPosition = ____roomGrid.gridCoordinatesToWorldPosition
local ____rooms = require("functions.rooms")
local setRoomCleared = ____rooms.setRoomCleared
local setRoomUncleared = ____rooms.setRoomUncleared
local ____spawnCollectible = require("functions.spawnCollectible")
local spawnCollectible = ____spawnCollectible.spawnCollectible
local ____types = require("functions.types")
local asCollectibleType = ____types.asCollectibleType
local asNumber = ____types.asNumber
local ____utils = require("functions.utils")
local assertDefined = ____utils.assertDefined
local ____ReadonlySet = require("types.ReadonlySet")
local ReadonlySet = ____ReadonlySet.ReadonlySet
local ____Feature = require("classes.private.Feature")
local Feature = ____Feature.Feature
function spawnGridEntityForJSONRoom(self, gridEntityXMLType, gridEntityXMLVariant, x, y)
    local room = game:GetRoom()
    local gridEntityTuple = convertXMLGridEntityType(nil, gridEntityXMLType, gridEntityXMLVariant)
    if gridEntityTuple == nil then
        return nil
    end
    local gridEntityType, variant = table.unpack(gridEntityTuple)
    local position = gridCoordinatesToWorldPosition(nil, x, y)
    local gridIndex = room:GetGridIndex(position)
    local gridEntity = spawnGridEntityWithVariant(nil, gridEntityType, variant, gridIndex)
    if gridEntity == nil then
        return gridEntity
    end
    if gridEntityType == GridEntityType.POOP then
        local sprite = gridEntity:GetSprite()
        sprite:Play("State1", true)
        sprite:SetLastFrame()
    end
    return gridEntity
end
function fixPitGraphics(self)
    local room = game:GetRoom()
    local gridWidth = room:GetGridWidth()
    local pitMap = getPitMap(nil)
    for ____, ____value in __TS__Iterator(pitMap) do
        local gridIndex = ____value[1]
        local gridEntity = ____value[2]
        local gridIndexLeft = gridIndex - 1
        local L = pitMap:has(gridIndexLeft)
        local gridIndexRight = gridIndex + 1
        local R = pitMap:has(gridIndexRight)
        local gridIndexUp = gridIndex - gridWidth
        local U = pitMap:has(gridIndexUp)
        local gridIndexDown = gridIndex + gridWidth
        local D = pitMap:has(gridIndexDown)
        local gridIndexUpLeft = gridIndex - gridWidth - 1
        local UL = pitMap:has(gridIndexUpLeft)
        local gridIndexUpRight = gridIndex - gridWidth + 1
        local UR = pitMap:has(gridIndexUpRight)
        local gridIndexDownLeft = gridIndex + gridWidth - 1
        local DL = pitMap:has(gridIndexDownLeft)
        local gridIndexDownRight = gridIndex + gridWidth + 1
        local DR = pitMap:has(gridIndexDownRight)
        local pitFrame = getPitFrame(
            nil,
            L,
            R,
            U,
            D,
            UL,
            UR,
            DL,
            DR
        )
        local sprite = gridEntity:GetSprite()
        sprite:SetFrame(pitFrame)
    end
end
function getPitMap(self)
    local pitMap = __TS__New(Map)
    for ____, gridEntity in ipairs(getGridEntities(nil, GridEntityType.PIT)) do
        local gridIndex = gridEntity:GetGridIndex()
        pitMap:set(gridIndex, gridEntity)
    end
    return pitMap
end
function getPitFrame(self, L, R, U, D, UL, UR, DL, DR)
    local F = 0
    if L then
        F = F | 1
    end
    if U then
        F = F | 2
    end
    if R then
        F = F | 4
    end
    if D then
        F = F | 8
    end
    if U and L and not UL and not R and not D then
        F = 17
    end
    if U and R and not UR and not L and not D then
        F = 18
    end
    if L and D and not DL and not U and not R then
        F = 19
    end
    if R and D and not DR and not L and not U then
        F = 20
    end
    if L and U and R and D and not UL then
        F = 21
    end
    if L and U and R and D and not UR then
        F = 22
    end
    if U and R and D and not L and not UR then
        F = 25
    end
    if L and U and D and not R and not UL then
        F = 26
    end
    if L and U and R and D and not DL and not DR then
        F = 24
    end
    if L and U and R and D and not UR and not UL then
        F = 23
    end
    if L and U and R and UL and not UR and not D then
        F = 27
    end
    if L and U and R and UR and not UL and not D then
        F = 28
    end
    if L and U and R and not D and not UR and not UL then
        F = 29
    end
    if L and R and D and DL and not U and not DR then
        F = 30
    end
    if L and R and D and DR and not U and not DL then
        F = 31
    end
    if L and R and D and not U and not DL and not DR then
        F = 32
    end
    return F
end
local GRID_ENTITY_XML_TYPE_SET = __TS__New(ReadonlySet, GRID_ENTITY_XML_TYPE_VALUES)
____exports.DeployJSONRoom = __TS__Class()
local DeployJSONRoom = ____exports.DeployJSONRoom
DeployJSONRoom.name = "DeployJSONRoom"
__TS__ClassExtends(DeployJSONRoom, Feature)
function DeployJSONRoom.prototype.____constructor(self, preventGridEntityRespawn)
    Feature.prototype.____constructor(self)
    self.featuresUsed = {ISCFeature.PREVENT_GRID_ENTITY_RESPAWN}
    self.preventGridEntityRespawn = preventGridEntityRespawn
end
function DeployJSONRoom.prototype.spawnAllEntities(self, jsonRoom, rng, verbose)
    if verbose == nil then
        verbose = false
    end
    local shouldUnclearRoom = false
    for ____, jsonSpawn in ipairs(jsonRoom.spawn) do
        local xString = jsonSpawn["$"].x
        local x = tonumber(xString)
        assertDefined(nil, x, "Failed to convert the following x coordinate to a number (for a spawn): " .. xString)
        local yString = jsonSpawn["$"].y
        local y = tonumber(yString)
        assertDefined(nil, y, "Failed to convert the following y coordinate to a number (for a spawn): " .. yString)
        local jsonEntity = getRandomJSONEntity(nil, jsonSpawn.entity, rng)
        local entityTypeString = jsonEntity["$"].type
        local entityTypeNumber = tonumber(entityTypeString)
        assertDefined(nil, entityTypeNumber, "Failed to convert the entity type to a number: " .. entityTypeString)
        local variantString = jsonEntity["$"].variant
        local variant = tonumber(variantString)
        assertDefined(
            nil,
            variant,
            "Failed to convert the entity variant to a number: " .. tostring(variant)
        )
        local subTypeString = jsonEntity["$"].subtype
        local subType = tonumber(subTypeString)
        assertDefined(
            nil,
            subType,
            "Failed to convert the entity sub-type to a number: " .. tostring(subType)
        )
        local isGridEntity = GRID_ENTITY_XML_TYPE_SET:has(entityTypeNumber)
        if isGridEntity then
            local gridEntityXMLType = entityTypeNumber
            if verbose then
                log(((((((("Spawning grid entity " .. tostring(gridEntityXMLType)) .. ".") .. tostring(variant)) .. " at: (") .. tostring(x)) .. ", ") .. tostring(y)) .. ")")
            end
            spawnGridEntityForJSONRoom(
                nil,
                gridEntityXMLType,
                variant,
                x,
                y
            )
        else
            local entityType = entityTypeNumber
            if verbose then
                local entityID = getEntityIDFromConstituents(nil, entityType, variant, subType)
                log(((((("Spawning normal entity " .. entityID) .. " at: (") .. tostring(x)) .. ", ") .. tostring(y)) .. ")")
            end
            local entity = self:spawnNormalEntityForJSONRoom(
                entityType,
                variant,
                subType,
                x,
                y,
                rng
            )
            local npc = entity:ToNPC()
            if npc ~= nil and npc.CanShutDoors then
                shouldUnclearRoom = true
            end
        end
    end
    if shouldUnclearRoom then
        if verbose then
            log("Setting the room to be uncleared since there were one or more battle NPCs spawned.")
        end
        setRoomUncleared(nil)
    elseif verbose then
        log("Leaving the room cleared since there were no battle NPCs spawned.")
    end
end
function DeployJSONRoom.prototype.spawnNormalEntityForJSONRoom(self, entityType, variant, subType, x, y, rng)
    local room = game:GetRoom()
    local roomType = room:GetType()
    local position = gridCoordinatesToWorldPosition(nil, x, y)
    local seed = rng:Next()
    local entity
    if entityType == EntityType.PICKUP and variant == asNumber(nil, PickupVariant.COLLECTIBLE) then
        local options = roomType == RoomType.ANGEL
        entity = spawnCollectible(
            nil,
            asCollectibleType(nil, subType),
            position,
            seed,
            options
        )
    else
        entity = spawnWithSeed(
            nil,
            entityType,
            variant,
            subType,
            position,
            seed
        )
    end
    if entityType == EntityType.PITFALL and variant == asNumber(nil, PitfallVariant.PITFALL) then
        entity.EntityCollisionClass = EntityCollisionClass.ENEMIES
        entity.GridCollisionClass = EntityGridCollisionClass.WALLS
    end
    return entity
end
function DeployJSONRoom.prototype.deployJSONRoom(self, jsonRoom, seedOrRNG, verbose)
    if verbose == nil then
        verbose = false
    end
    local rng = isRNG(nil, seedOrRNG) and seedOrRNG or newRNG(nil, seedOrRNG)
    if verbose then
        log("Starting to empty the room of entities and grid entities.")
    end
    emptyRoom(nil)
    if verbose then
        log("Finished emptying the room of entities and grid entities.")
    end
    setRoomCleared(nil)
    if verbose then
        log("Starting to spawn all of the new entities and grid entities.")
    end
    self:spawnAllEntities(jsonRoom, rng, verbose)
    if verbose then
        log("Finished spawning all of the new entities and grid entities.")
    end
    fixPitGraphics(nil)
    self.preventGridEntityRespawn:preventGridEntityRespawn()
end
__TS__DecorateLegacy({Exported}, DeployJSONRoom.prototype, "deployJSONRoom", true)
return ____exports
