local tilesStruct = require("structs.tiles")
local configs = require("configs")
local state = require("loaded_state")
local viewportHandler = require("viewport_handler")
local toolUtils = require("tool_utils")
local brushUtils = require("brushes")
local placementUtils = require("placement_utils")
local celesteRender = require("celeste_render")
local utils = require("utils")

local script = {
    name = "lavify",
    displayName = "Lavify",
    parameters = {
        ignoreSpawnpoints = "No",
    },
    fieldInformation = {
        ignoreSpawnpoints = {
            fieldType = "loennScripts.dropdown",
            options = {
                "Yes", "No"
            }
        }
    },
    tooltip = "Turns the floor into lava (WARNING: Undo only undos the room selected when lavifying)",
    tooltips = {
        ignoreSpawnpoints = "If spawnpoints are not ignored, lava will not be placed under them",
    },
}

local function redrawLayer(room, layer)
    local selected = state.isItemSelected(room)

    if selected then
        toolUtils.redrawTargetLayer(room, layer)
    else
        celesteRender.forceRedrawRoom(room, state, false)
    end
end

local function lavifyRoom(room, ignoreSpawnpoints)
    local foregroundMatrix = room.tilesFg.matrix
    local x = room.tilesFg.matrix._width
    
    -- Create 2D table
    local xCounter = 1
    local yIndex = 1
    local newMatrix = {[1] = {}}
    
    for i,v in ipairs(foregroundMatrix) do
        table.insert(newMatrix[yIndex], v)
        xCounter += 1
        if xCounter > x then
            xCounter = 1
            table.insert(newMatrix, {})
            yIndex += 1
        end
    end

    -- Add spawnpoints
    local entities = room.entities

    if not ignoreSpawnpoints then
        for i,v in ipairs(entities) do
            if v._name == "player" then
                newMatrix[v.y/8][v.x/8] = "#"
                newMatrix[v.y/8][v.x/8 + 1] = "#"
            end
        end
    end

    -- Add lava locations
    for i,v in ipairs(newMatrix) do
        for j,w in ipairs(newMatrix[i]) do
            if newMatrix[i-1] then
                if newMatrix[i][j] ~= "0" and newMatrix[i][j] ~= "#" then
                    if newMatrix[i-1][j] == "0" then
                        newMatrix[i][j] = "@"
                    end
                end
            end
        end
    end

    -- Place lava
    local lavaLength = 0
    local lavaX = 0
    local lavaY = 0
    for i,v in ipairs(newMatrix) do
        for j,w in ipairs(newMatrix[i]) do
            local tile = newMatrix[i][j]

            if tile == "@" then
                if lavaLength == 0 then
                    lavaX = j
                    lavaY = i
                end
                lavaLength += 1
            elseif lavaLength > 0 then
                lavaLength = 0
                
                local tempJ = j
                if tempJ == 1 then
                    tempJ = #newMatrix[i] + 1
                end
                table.insert(entities, {
                    ["_type"] = "entity",
                    ["_name"] = "fireBarrier",
                    ["width"] = (tempJ - lavaX) * 8,
                    ["height"] = 8,
                    ["x"] = lavaX * 8 - 8,
                    ["y"] = lavaY * 8 - 8
                })
                placementUtils.finalizePlacement(room, "entities", entities[#entities])
            end
        end
    end

    -- Remove tiles that are now lava
    for i,v in ipairs(newMatrix) do
        for j,w in ipairs(newMatrix[i]) do
            if newMatrix[i][j] == "@" then
                brushUtils.placeTileRaw(room, j, i, "0", "tilesFg")
            end
        end
    end

    -- Redraw layers
    redrawLayer(room, "tilesFg")
    redrawLayer(room, "entities")
end

function script.run(room, args)
    local ignoreSpawnpoints = args.ignoreSpawnpoints == "Yes"
    for i,r in pairs(state.map.rooms) do
        lavifyRoom(r, ignoreSpawnpoints)
    end
end

return script