local waterbombs
local replaceableTiles = {
    ["water"] = "grass-1",
    ["deepwater"] = "grass-1",
    ["water-green"] = "grass-1",
    ["deepwater-green"] = "grass-1"
}


script.on_configuration_changed(function(data)
    if waterbombs ~= nil then
        script.on_event(defines.events.on_tick, tickBombs)
    end
end)


script.on_load(function(event)
    if waterbombs ~= nil then
        script.on_event(defines.events.on_tick, tickBombs)
    end
end)


script.on_event(defines.events.on_built_entity, function(event)
    if event.entity.name == "waterbomb" then
        waterbombs = {}
        for _, surface in pairs(game.surfaces) do
            for _, entity in pairs(surface.find_entities_filtered{name="waterbomb"}) do
                table.insert(waterbombs, entity)
            end
        end
        script.on_event(defines.events.on_tick, tickBombs)
    end
end)


function tickBombs(event)
    if event.tick % 20 == 0 then
        for k,e in pairs(waterbombs) do
            if not e.valid then
                table.remove(waterbombs, k)

            elseif e.energy > 49000000 then
                local epos, x, y, distX, distY, surface
                local explosionRadius = settings.global["Waterbomb-explosion-radius"].value

                epos = e.position
                x = epos.x
                y = epos.y
                surface =  e.surface

                -- create explosions
                for xx = x - explosionRadius, x + explosionRadius, 2 do
                    for yy = y - explosionRadius, y + explosionRadius, 2 do
                        distX = math.abs(x - xx)
                        distY = math.abs(y - yy)

                        if math.floor(math.sqrt((distX * distX) + (distY * distY))) <= explosionRadius then
                            e.surface.create_entity({name = "medium-explosion", position = {x = xx, y = yy}})
                        end
                    end
                end

                -- big detonation
                e.surface.create_entity({name = "waterbomb-detonation", position = e.position, target = e, speed = 1})

                -- bomb explodes
                e.destroy()
                table.remove(waterbombs, k)

                -- water is created
                createWater(x, y, explosionRadius, surface)
                throwDirt(x, y, explosionRadius, surface)

                -- random stones
                for a = 1, (explosionRadius * 10) do
                    createRandomStone(epos, surface)
                    createRandomStone(epos, surface)
                end
            end
        end

        -- nothing more to be exploded. Stop ticking.
        if #waterbombs == 0 then
            waterbombs = nil
            script.on_event(defines.events.on_tick, nil)
        end
    end
end

function createWater(x, y, size, surface)
    -- Setting tiles to water where player characters are standing deletes the character and sets them to god mode. We dont want that.
    local players = surface.find_entities_filtered({area = {{x - size - 1, y - size - 1}, {x + size + 1, y + size + 1}}, type="character"})
    if #players ~= 0 then
        return
    end

    local waterTiles = {}
    x = math.floor(x)
    y = math.floor(y)

    for wx = x - size, x + size, 1 do
        for wy = y - size, y + size, 1 do
        table.insert(waterTiles, {name="water", position={wx, wy}})
        end
    end
    surface.set_tiles(waterTiles)

    waterTiles = {}
    table.insert(waterTiles, {name="deepwater", position={x, y}})
    surface.set_tiles(waterTiles)
end


function throwDirt(x, y, size, surface)
    local dirtTiles = {}
    local tileName
    local distX,distY

    if settings.global["Waterbomb-throw-dirt"].value == true then
        x = math.floor(x)
        y = math.floor(y)

        for xx = x - size, x + (size + 1), 1 do
            for yy = y - size, y + (size + 1), 1 do
                distX = math.abs(x - xx)
                distY = math.abs(y - yy)

                if math.floor(math.random(1, 4)) >= 4 then
                    table.insert(dirtTiles, {name = "grass-1", position = {xx, yy}})
                end
            end
        end

        if #dirtTiles ~= 0 then
            surface.set_tiles(dirtTiles)
        end
    end
end


function createRandomStone(position, surface)
    local x,y
    local maximumRockThrowDistance = settings.global["Waterbomb-explosion-radius"].value + 7

    if settings.global["Waterbomb-throw-stone"].value == true then
        x = position.x
        y = position.y

        if math.random() > 0.5 then
            x = x - math.floor(math.random(1, maximumRockThrowDistance))
            else
            x = x + math.floor(math.random(1, maximumRockThrowDistance))
        end

        if math.random() < 0.5 then
            y = y - math.floor(math.random(1, maximumRockThrowDistance))
            else
            y = y + math.floor(math.random(1, maximumRockThrowDistance))
        end

        if math.floor(math.random(1, 4)) >= 3 then
            if settings.global["Waterbomb-throw-stone-into-water"].value == true then
                surface.set_tiles({{name="grass-1", position={math.floor(x), math.floor(y)}}})
            end

            local tileName = surface.get_tile(math.floor(x), math.floor(y)).name
            if not replaceableTiles[tileName] then
                surface.create_entity({name="stone", position={x, y}}).amount = math.floor(math.random(13, 37))
                surface.create_entity({name="explosion", position={x, y}})
            end
        end
    end
end