local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)

local function sch(name)
    return (mod_path .. "/schematics/" .. name .. ".mts")
end

local level = 167

local light_noise = PerlinNoise({
    offset = 0.5,
    scale = 0.5,
    spread = {x = 60, y = 60, z = 60},
    seed = 654643 + core.get_mapgen_setting("seed"),
    octaves = 3,
    persist = 0.2,
    lacunarity = 2.0,
})
local light_nodes = {
    "br_core:ceiling_light_0",
    "br_core:ceiling_light_1",
    "br_core:ceiling_light_2",
    "br_core:ceiling_light_3",
    "br_core:emergency_light_0",
    "br_core:emergency_light_1",
}
local light_cids = {}
core.register_on_mods_loaded(function()
    for i, name in ipairs(light_nodes) do
        light_cids[core.get_content_id(name)] = name
    end
end)
-- streets
br_core.register_level({
    level = level,
    desc = "Level 167",
    danger = 2,
    grace_dist = 5,
    biome = {},
    segsize = 16,
    shift_x = 8,
    biome_roughness = 2.728,
    -- level_height = 160,
    biome_pixelization = 3,
    base_height = 17,
    -- on_generate = function(self, pos, perlin)
    -- end,
    sun = {
        visible = true,
        texture = "blank.png",
        sunrise_visible = false,
    },
    moon = {
        visible = false,
    },
    clouds = {
        density = 0.6,
        thickness = 2.3,
        ambient = "#333",
        color = "#33333320",
        height = level * br_core.level_height - br_core.offset + 80 + 50,
        speed = {x=6.9, z=12}
    },
    sky = {
		base_color = "#ffffff",
		type = "regular",
		clouds = true,
		sky_color = {
			day_sky = "#b1b2b1" ,
			day_horizon = "#6a6270",
			dawn_sky = "#5d5d5f" ,
			dawn_horizon = "#6e5766",
			night_sky = "#fff" ,
			night_horizon = "#fff",
			indoors = "#3b3b3b",
			fog_sun_tint = "#263965",
			fog_moon_tint = "#263965",
			fog_tint_type = "custom",
		},
        fog = {
            fog_start = 0.1,
            fog_distance = -1,
        },
	},
    after_generated = function(pos, cid)
        if not light_cids[cid] then return false end
        local v = light_noise:get_3d(pos)
        if (v < 0.4) then
            local node = core.get_node(pos)
            node.name = node.name .. "_off"
            if core.registered_nodes[node.name] then
                core.set_node(pos, node)
                return true
            end
        end
        return false
    end,
})
local l167pl = {}
local l167timer = -1
br_core.register_on_level_enter(function(player, from_level, to_level)
    if to_level == level then
        l167pl[player] = true
        player:override_day_night_ratio(1)
    end
end)
br_core.register_on_level_exit(function(player, from_level, to_level)
    if from_level == level then
        l167pl[player] = nil
        player:override_day_night_ratio(1)
    end
end)


minetest.register_globalstep(function(dtime)
    local day_period = 600
    if l167timer == -1 then
        l167timer = world_storage:get_key("l167timer") or (day_period * 0.6)
    end
    if (math.floor(l167timer + dtime) ~= math.floor(l167timer)) then
        world_storage:set_key("l167timer", l167timer)
    end
    l167timer = (l167timer + dtime) % day_period
    for player,_ in pairs(l167pl) do
        if player and player.is_player and player:is_player() then
            local val = math.sin(l167timer / day_period * 3.14) * 1.4 - 0.2
            val = math.max(0, math.min(1, val)) * 0.7
            player:override_day_night_ratio(val)
            -- player:override_day_night_ratio( 0.2 + math.sin(l167timer / day_period * 3.14) * 0.3)
            local pos = player:get_pos()
            for i=0, 1 do
                local light = br_core.get_natural_light(pos, 0.5)
                if light >= 14 then
                    local pp = vector.new(
                        (br_core.rand_range(pos.x-40, pos.x+40)),
                        (br_core.rand_range(pos.y-2,  pos.y+18)),
                        (br_core.rand_range(pos.z-40, pos.z+40))
                    )
                    local vel = vector.new(
                        (br_core.rand_range(3, 8)),
                        (br_core.rand_range(-1, 1)),
                        (br_core.rand_range(3, 8))
                    )
                    pp = vector.offset(pp, -10, 0, -10)
                    minetest.add_particle({
                        pos = pp,
                        velocity = vel,
                        playername = player:get_player_name(),
                        expirationtime = 4,
                        collisiondetection = true,
                        collision_removal = true,
                        texture = "br_dust_particle.png",
                        size = 1
                    })
                end
            end
        end
    end
end)
br_core.register_biome({
    level = level,
    desc = "Normal",
    -- name = "NW",
    danger = 2,
    on_generate = nil,
    segheight = 16,
    can_generate = function(pos)
        return (pos.x % 73 > 20 and pos.z % 92 < 20)
    end,
    schems = {
        {name=sch("167_main_0"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_1"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_2"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_3"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_3_portal"),    vertical_segments={1,1,1,1,1}, prevalence=2, can_generate=function(pos)
            return (pos.x%3==0 or pos.z%4==0)
        end},
        {name=sch("167_main_4"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_5"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_6"),      free_rotation=true, vertical_segments={1,1,1,1,1}},
        {name=sch("167_main_6_portal"), free_rotation=true, vertical_segments={1,1,1,1,1}, can_generate=function(pos)
            return (pos.x%3==1 or pos.z%3==1)
        end},
        {name=sch("167_main_7"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_7_portal"), free_rotation=true, vertical_segments={1,1,1,1,1}, can_generate=function(pos)
            return (pos.x%3==2 or pos.z%4==0)
        end},
        {name=sch("167_main_8"),      free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_main_8_portal"), free_rotation=true, vertical_segments={1,1,1,1,1}, can_generate=function(pos)
            return (pos.x%3==1 or pos.z%3==1)
        end},
        {name=sch("167_apartment_1"), free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=3},
        {name=sch("167_flat_0"),      free_rotation=true, vertical_segments={0,0,0,1,1}, prevalence=7},
        {name=sch("167_flat_1"),      free_rotation=true, vertical_segments={0,0,0,1,1}, prevalence=7},
        {name=sch("167_flat_2"),      free_rotation=true, vertical_segments={0,0,0,1,1}, prevalence=7},
        {name=sch("167_flat_3"),      free_rotation=true, vertical_segments={0,0,0,1,1}, prevalence=7},
        {name=sch("167_stairs_0"),    free_rotation=true, vertical_segments={1,1,1,1,0}, skip_above=1},
        {name=sch("167_stairs_1"),    free_rotation=true, vertical_segments={1,1,1,1,0}, skip_above=1},
        {name=sch("167_stairs_2"),    free_rotation=true, vertical_segments={1,1,1,1,0}, skip_above=1},
    }
})
br_core.register_biome({
    level = level,
    desc = "Valley",
    -- name = "NW",
    danger = 2,
    on_generate = nil,
    segheight = 16,
    can_generate = function(pos)
        return not (pos.x % 73 < 20 and pos.z % 92 < 20)
    end,
    schems = {
        {name=sch("167_main_0"),    free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_1"),    free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_2"),    free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_3"),    free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_3_portal"),    vertical_segments={1,1,0,0,0}, can_generate=function(pos)
            return (pos.x%3==0 or pos.z%2==0)
        end},
        {name=sch("167_main_1"),    free_rotation=true, vertical_segments={1,1,1,0,0}},
        {name=sch("167_main_5"),    free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_6"),    free_rotation=true, vertical_segments={1,1,1,0,0}},
        {name=sch("167_main_6_portal"), free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_7"),      free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_7_portal"), free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_8"),      free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_main_8_portal"), free_rotation=true, vertical_segments={1,1,0,0,0}},
        {name=sch("167_tall_block_0"), free_rotation=true, vertical_segments={0,0,1,0,0}, skip_above=1},
        {name=sch("167_tall_block_1"), free_rotation=true, vertical_segments={0,0,1,0,0}, skip_above=1},
        {name=sch("167_tall_block_2"), free_rotation=true, vertical_segments={0,1,1,0,0}, skip_above=1},
        {name=sch("167_flat_0"),    free_rotation=true, vertical_segments={0,1,1,0,0}, prevalence=4},
        {name=sch("167_flat_1"),    free_rotation=true, vertical_segments={0,1,1,0,0}, prevalence=4},
        {name=sch("167_flat_2"),    free_rotation=true, vertical_segments={0,1,1,0,0}, prevalence=4},
        {name=sch("167_flat_3"),    free_rotation=true, vertical_segments={0,1,1,0,0}, prevalence=7},
        {name=sch("167_stairs_0"),  free_rotation=true, vertical_segments={1,1,0,0,0}, skip_above=1},
        {name=sch("167_stairs_1"),  free_rotation=true, vertical_segments={1,1,0,0,0}, skip_above=1},
        {name=sch("167_stairs_2"),  free_rotation=true, vertical_segments={1,1,0,0,0}, skip_above=1},
    }
})
br_core.register_biome({
    level = level,
    desc = "Apartments",
    -- name = "NW",
    danger = 2,
    on_generate = nil,
    segheight = 16,
    prevalence = 3,
    can_generate = function(pos)
        return (pos.x % 73 < 20 and pos.z % 92 < 20)
    end,
    schems = {
        {name=sch("167_apartment_0"), free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=4},
        {name=sch("167_apartment_0_portal"), free_rotation=true, vertical_segments={1,1,1,1,1}, prevalence=1, can_generate=function(pos)
            return (pos.x%2==0 or pos.z%3==0)
        end},
        {name=sch("167_apartment_1"), free_rotation=true, vertical_segments={1,1,1,1,1}},
        {name=sch("167_apartment_2"), free_rotation=true, vertical_segments={1,1,1,1,1}},
        {name=sch("167_apartment_3"), free_rotation=true, vertical_segments={1,1,1,1,1}},
        {name=sch("167_flat_3"),      free_rotation=true, vertical_segments={1,1,}, prevalence=2, skip_above=4},
        {name=sch("167_stairs_0"),    free_rotation=true, vertical_segments={1,1,1,1,0}, skip_above=1},
        {name=sch("167_stairs_1"),    free_rotation=true, vertical_segments={1,1,1,1,0}, skip_above=1},
        {name=sch("167_stairs_2"),    free_rotation=true, vertical_segments={1,1,1,1,0}, skip_above=1},
    }
})
minetest.register_ore({
    ore_type       = "stratum",
    ore            = "br_core:concrete_ruined_grey",
    wherein        = {"air", "group:liquid", "group:solid"},
    y_min = level * br_core.level_height - br_core.offset,
    y_max = level * br_core.level_height - br_core.offset,
})

br_core.register_level_sound({
    level = level,
    time = 10,
    scare_timer = {},
    wind_gust_timer = {},
    on_play = function(self, dtime, player)
        local playing = br_core.sound_get_tag("level167_wind", player)
        local light = br_core.get_natural_light(player:get_pos(), 0.5) or 0
        if (playing == nil or #playing < 1
        or (playing and playing[1].fading and #playing <= 1))
        and light > 13 then
            br_core.sound_play("level167_wind", player, {
                name = "br_wind_noise_WTFPL_Sumianvoice",
                level = level,
                gain = (br_sounds.master or 1) * (0.5 * math.random() + 0.5) * (light-4) / 10,
                fade = 0.5,
                to_player = player:get_player_name(),
                time = 7,
            })
        elseif playing and #playing >= 1 and light < 13 then
            br_core.sound_stop_tag("level167_wind", player, {
                fade = 0.5,
            })
        end
        playing = br_core.sound_get_tag("level167_traffic", player)
        if playing == nil or #playing < 1
        or (playing and playing[1].fading and #playing <= 1) then
            br_core.sound_play("level167_traffic", player, {
                name = "br_traffic_distant_cc0_klangfabrik",
                level = level,
                gain = (br_sounds.master or 1) * (0.2 * math.random() + 0.1),
                fade = 0.3,
                pitch = 0.8,
                max_hear_distance = 50,
                to_player = player:get_player_name(),
                time = 14,
            })
        end

        if self.scare_timer[player] == nil then self.scare_timer[player] = math.random(120, 200) end
        self.scare_timer[player] = self.scare_timer[player] - dtime
        playing = br_core.sound_get_tag("level167_beep", player)
        if (self.scare_timer[player] < 0) and (playing == nil or #playing < 1) then
            self.scare_timer[player] = math.random(60, 240)
            br_core.sound_play("level167_beep", player, {
                name = "br_level_0_beep",
                level = level,
                gain = (br_sounds.master or 1) * 0.2,
                to_player = player:get_player_name(),
                time = 1,
            })
        end


        if self.wind_gust_timer[player] == nil then self.wind_gust_timer[player] = math.random(10, 100) end
        self.wind_gust_timer[player] = self.wind_gust_timer[player] - dtime
        playing = br_core.sound_get_tag("level167_wind_gust", player)
        if ((self.wind_gust_timer[player] < 0) and (playing == nil or #playing < 1))
        and light > 13 then
            self.wind_gust_timer[player] = math.random(10, 100)
            br_core.sound_play("level167_wind_gust", player, {
                name = "br_wind_noise_heavy_WTFPL_Sumianvoice",
                level = level,
                gain = (br_sounds.master or 1) * 0.2,
                to_player = player:get_player_name(),
                fade = 0.2,
                time = 31,
            })
        elseif playing and #playing >= 0 and light < 13 then
            br_core.sound_stop_tag("level167_wind_gust", player, {
                fade = 0.2,
            })
        elseif self.wind_gust_timer[player] < 0 then
            self.wind_gust_timer[player] = math.random(10, 100)
        end
    end
})

-- junk and occasional supplies
br_core.set_loot_table(level, 0, {
    node_names = {"br_core:loot_crate"},
    max_items = 4,
    items = {
        br_core.loot.list.junk(5),
        br_core.loot.list.junk(5),
        br_core.loot.list.food(32),
        br_core.loot.list.food(32),
        br_core.loot.list.drinks(32),
        br_core.loot.list.drinks(32),
        {items = {"br_core:key_2 1"}, rarity = 22},
        {items = {"br_core:key_3 1"}, rarity = 22},
    },
})
-- food
br_core.set_loot_table(level, 1, {
    node_names = {"br_core:loot_crate"},
    max_items = 8,
    items = {
        br_core.loot.list.food(23),
        br_core.loot.list.food(23),
        br_core.loot.list.food(23),
    },
})
-- drinks
br_core.set_loot_table(level, 2, {
    node_names = {"br_core:loot_crate"},
    max_items = 8,
    items = {
        br_core.loot.list.drinks(8),
        br_core.loot.list.drinks(8),
        br_core.loot.list.drinks(8),
    },
})
-- tools and supplies
br_core.set_loot_table(level, 3, {
    node_names = {"br_core:loot_crate"},
    max_items = 8,
    items = {
        br_core.loot.list.tools(3),
        br_core.loot.list.junk(3),
        br_core.loot.list.junk(3),
        {items = {"br_core:key_2 1"}, rarity = 22},
        {items = {"br_core:key_3 1"}, rarity = 22},
    },
})
-- jackpot
br_core.set_loot_table(level, 4, {
    node_names = {"br_core:loot_crate"},
    max_items = 16,
    items = {
        br_core.loot.list.food(6),
        br_core.loot.list.food(6),
        br_core.loot.list.drinks(6),
        br_core.loot.list.drinks(6),
        br_core.loot.list.tools(4),
        {items = {"br_core:key_2 1"}, rarity = 8},
        {items = {"br_core:key_3 1"}, rarity = 14},
        br_core.loot.list.junk(5),
        br_core.loot.list.junk(5),
        br_core.loot.list.junk(5),
    },
})
-- keys
br_core.set_loot_table(level, 8, {
    node_names = {"br_core:loot_crate"},
    max_items = 8,
    items = {
        {items = {"br_core:key_2 1"}, rarity = 8},
        {items = {"br_core:key_3 1"}, rarity = 14},
        br_core.loot.list.junk(8),
        br_core.loot.list.junk(8),
        br_core.loot.list.tools(8),
    },
})

br_core.add_loot_ore(level, {
    wherein = "br_core:loot_area_0",
    node_name = "br_core:loot_crate_0",
    rarity = 70,
})

br_core.add_loot_ore(level, {
    wherein = "br_core:loot_area_1",
    node_name = "br_core:loot_crate_1",
    rarity = 66,
})

br_core.add_loot_ore(level, {
    wherein = "br_core:loot_area_2",
    node_name = "br_core:loot_crate_2",
    rarity = 54,
})

br_core.add_loot_ore(level, {
    wherein = "br_core:loot_area_3",
    node_name = "br_core:loot_crate_3",
    rarity = 54,
})
