local silver_enabled = core.settings:get_bool("yams_enable_silver", false)

-- Mostly copied from minetest_game
local function register_yams_ores()

    -- Stratum ores.
    -- These obviously first.

    -- Silver sandstone

    core.register_ore({
        ore_type        = "stratum",
        ore             = "default:silver_sandstone",
        wherein         = {"default:stone"},
        clust_scarcity  = 1,
        y_max           = 46,
        y_min           = 10,
        noise_params    = {
            offset = 28,
            scale = 16,
            spread = {x = 128, y = 128, z = 128},
            seed = 90122,
            octaves = 1,
        },
        stratum_thickness = 4,
        biomes = {"cold_desert"},
    })

    core.register_ore({
        ore_type        = "stratum",
        ore             = "default:silver_sandstone",
        wherein         = {"default:stone"},
        clust_scarcity  = 1,
        y_max           = 42,
        y_min           = 6,
        noise_params    = {
            offset = 24,
            scale = 16,
            spread = {x = 128, y = 128, z = 128},
            seed = 90122,
            octaves = 1,
        },
        stratum_thickness = 2,
        biomes = {"cold_desert"},
    })

    -- Desert sandstone

    core.register_ore({
        ore_type        = "stratum",
        ore             = "default:desert_sandstone",
        wherein         = {"default:desert_stone"},
        clust_scarcity  = 1,
        y_max           = 46,
        y_min           = 10,
        noise_params    = {
            offset = 28,
            scale = 16,
            spread = {x = 128, y = 128, z = 128},
            seed = 90122,
            octaves = 1,
        },
        stratum_thickness = 4,
        biomes = {"desert"},
    })

    core.register_ore({
        ore_type        = "stratum",
        ore             = "default:desert_sandstone",
        wherein         = {"default:desert_stone"},
        clust_scarcity  = 1,
        y_max           = 42,
        y_min           = 6,
        noise_params    = {
            offset = 24,
            scale = 16,
            spread = {x = 128, y = 128, z = 128},
            seed = 90122,
            octaves = 1,
        },
        stratum_thickness = 2,
        biomes = {"desert"},
    })

    -- Sandstone

    core.register_ore({
        ore_type        = "stratum",
        ore             = "default:sandstone",
        wherein         = {"default:desert_stone"},
        clust_scarcity  = 1,
        y_max           = 39,
        y_min           = 3,
        noise_params    = {
            offset = 21,
            scale = 16,
            spread = {x = 128, y = 128, z = 128},
            seed = 90122,
            octaves = 1,
        },
        stratum_thickness = 2,
        biomes = {"desert"},
    })

    -- Blob ore.
    -- These before scatter ores to avoid other ores in blobs.

    -- Clay

    core.register_ore({
        ore_type        = "blob",
        ore             = "default:clay",
        wherein         = {"default:sand"},
        clust_scarcity  = 16 * 16 * 16,
        clust_size      = 5,
        y_max           = 0,
        y_min           = -15,
        noise_threshold = 0.0,
        noise_params    = {
            offset = 0.5,
            scale = 0.2,
            spread = {x = 5, y = 5, z = 5},
            seed = -316,
            octaves = 1,
            persist = 0.0
        },
    })

    -- Silver sand

    core.register_ore({
        ore_type        = "blob",
        ore             = "default:silver_sand",
        wherein         = {"default:stone"},
        clust_scarcity  = 16 * 16 * 16,
        clust_size      = 5,
        y_max           = 31000,
        y_min           = -31000,
        noise_threshold = 0.0,
        noise_params    = {
            offset = 0.5,
            scale = 0.2,
            spread = {x = 5, y = 5, z = 5},
            seed = 2316,
            octaves = 1,
            persist = 0.0
        },
    })

    -- Dirt

    core.register_ore({
        ore_type        = "blob",
        ore             = "default:dirt",
        wherein         = {"default:stone"},
        clust_scarcity  = 16 * 16 * 16,
        clust_size      = 5,
        y_max           = 31000,
        y_min           = -31,
        noise_threshold = 0.0,
        noise_params    = {
            offset = 0.5,
            scale = 0.2,
            spread = {x = 5, y = 5, z = 5},
            seed = 17676,
            octaves = 1,
            persist = 0.0
        },
        -- Only where default:dirt is present as surface material
        biomes = {"taiga", "snowy_grassland", "grassland", "coniferous_forest",
                "deciduous_forest", "deciduous_forest_shore", "rainforest",
                "rainforest_swamp"}
    })

    -- Gravel

    core.register_ore({
        ore_type        = "blob",
        ore             = "default:gravel",
        wherein         = {"default:stone"},
        clust_scarcity  = 16 * 16 * 16,
        clust_size      = 5,
        y_max           = 31000,
        y_min           = -31000,
        noise_threshold = 0.0,
        noise_params    = {
            offset = 0.5,
            scale = 0.2,
            spread = {x = 5, y = 5, z = 5},
            seed = 766,
            octaves = 1,
            persist = 0.0
        },
    })

    -- Scatter ores

    -- Coal

    -- s = clust_scarcity, n = clust_num_ores, c = clust_size
    local coal_defs = {{s = 8, n = 8, c = 3, y_max = 31000, y_min = 1025},
                       {s = 8, n = 8, c = 3, y_max = 64, y_min = -31000},
                       {s = 18, n = 22, c = 6, y_max = -512, y_min = -31000},
                       {s = 32, n = 36, c = 6, y_max = -2048, y_min = -31000}}

    for _, def in ipairs(coal_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_coal",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Tin

    local tin_defs = {{s = 13, n = 3, c = 3, y_max = 31000, y_min = 1025},
                      {s = 17, n = 1, c = 2, y_max = -16, y_min = -31000},
                      {s = 13, n = 3, c = 3, y_max = -64, y_min = -31000},
                      {s = 26, n = 5, c = 4, y_max = -512, y_min = -31000},
                      {s = 36, n = 11, c = 5, y_max = -4096, y_min = -31000}}

    for _, def in ipairs(tin_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_tin",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Copper

    local copper_defs = {{s = 11, n = 5, c = 3, y_max = 31000, y_min = 1025},
                         {s = 14, n = 2, c = 3, y_max = -16, y_min = -31000},
                         {s = 11, n = 5, c = 3, y_max = -64, y_min = -31000},
                         {s = 22, n = 9, c = 4, y_max = -512, y_min = -31000},
                         {s = 32, n = 17, c = 5, y_max = -4096, y_min = -31000}}

    for _, def in ipairs(copper_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_copper",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Iron

    local iron_defs = {{s = 11, n = 5, c = 3, y_max = 31000, y_min = 1025},
                       {s = 14, n = 2, c = 2, y_max = -64, y_min = -31000},
                       {s = 11, n = 5, c = 3, y_max = -128, y_min = -31000},
                       {s = 24, n = 23, c = 6, y_max = -1024, y_min = -31000},
                       {s = 36, n = 47, c = 8, y_max = -4096, y_min = -31000}}

    for _, def in ipairs(iron_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_iron",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Gold

    local gold_defs = {{s = 16, n = 3, c = 2, y_max = 31000, y_min = 1025},
                       {s = 20, n = 1, c = 2, y_max = -128, y_min = -31000},
                       {s = 16, n = 3, c = 3, y_max = -256, y_min = -31000},
                       {s = 28, n = 8, c = 4, y_max = -2048, y_min = -31000},
                       {s = 36, n = 15, c = 5, y_max = -8192, y_min = -31000}}

    for _, def in ipairs(gold_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_gold",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Mese crystal

    local mese_defs = {{s = 18, n = 6, c = 3, y_max = 31000, y_min = 1025},
                       {s = 22, n = 2, c = 2, y_max = -256, y_min = -31000},
                       {s = 18, n = 6, c = 3, y_max = -512, y_min = -31000},
                       {s = 28, n = 11, c = 5, y_max = -2048, y_min = -31000},
                       {s = 36, n = 23, c = 6, y_max = -8192, y_min = -31000}}

    for _, def in ipairs(mese_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_mese",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Diamond

    local diamond_defs = {{s = 18, n = 1, c = 2, y_max = 31000, y_min = 2049},
                          {s = 24, n = 1, c = 2, y_max = -512, y_min = -31000},
                          {s = 18, n = 3, c = 3, y_max = -1024, y_min = -31000},
                          {s = 24, n = 5, c = 3, y_max = -4096, y_min = -31000},
                          {s = 32, n = 9, c = 4, y_max = -8192, y_min = -31000},
                          {s = 40, n = 13, c = 6, y_max = -16384, y_min = -31000}}

    for _, def in ipairs(diamond_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:stone_with_diamond",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Mese block

    local mblk_defs = {{s = 36, n = 1, c = 2, y_max = 31000, y_min = 2049},
                       {s = 36, n = 1, c = 2, y_max = -1024, y_min = -31000},
                       {s = 36, n = 3, c = 3, y_max = -4096, y_min = -31000},
                       {s = 38, n = 6, c = 4, y_max = -8192, y_min = -31000},
                       {s = 40, n = 14, c = 6, y_max = -16384, y_min = -31000}}

    for _, def in ipairs(mblk_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "default:mese",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Mithril

    local mithril_defs = {{s = 20, n = 1, c = 2, y_max = 31000, y_min = 4097},
                          {s = 26, n = 1, c = 2, y_max = -1024, y_min = -31000},
                          {s = 20, n = 3, c = 3, y_max = -4096, y_min = -31000},
                          {s = 26, n = 5, c = 4, y_max = -8192, y_min = -31000},
                          {s = 34, n = 8, c = 4, y_max = -12288, y_min = -31000},
                          {s = 40, n = 12, c = 6, y_max = -16384, y_min = -31000}}

    for _, def in ipairs(mithril_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "moreores:mineral_mithril",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Egerum

    local egerum_defs = {{s = 13, n = 5, c = 3, y_max = 31000, y_min = 1025},
                         {s = 16, n = 2, c = 2, y_max = -16, y_min = -31000},
                         {s = 13, n = 5, c = 3, y_max = -64, y_min = -31000},
                         {s = 22, n = 9, c = 4, y_max = -512, y_min = -31000},
                         {s = 32, n = 22, c = 6, y_max = -2048, y_min = -31000}}

    for _, def in ipairs(egerum_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "magic_materials:stone_with_egerum",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Februm

    local februm_defs = {{s = 15, n = 3, c = 3, y_max = 31000, y_min = 1025},
                         {s = 20, n = 1, c = 2, y_max = -256, y_min = -31000},
                         {s = 15, n = 3, c = 3, y_max = -512, y_min = -31000},
                         {s = 24, n = 7, c = 4, y_max = -2048, y_min = -31000},
                         {s = 36, n = 13, c = 5, y_max = -4096, y_min = -31000}}

    for _, def in ipairs(februm_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "magic_materials:stone_with_februm",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- YAMS-TODO: temporary
    local stardust_defs = {{s = 19, n = 3, c = 3, y_max = 31000, y_min = 1025}}

    for _, def in ipairs(stardust_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "stardust:stone_with_stardust",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
    end

    -- Same as copper
    local silver_defs = {{s = 11, n = 5, c = 3, y_max = 31000, y_min = 1025},
                         {s = 14, n = 2, c = 3, y_max = -16, y_min = -31000},
                         {s = 11, n = 5, c = 3, y_max = -64, y_min = -31000},
                         {s = 22, n = 9, c = 4, y_max = -512, y_min = -31000},
                         {s = 32, n = 17, c = 5, y_max = -4096, y_min = -31000}}

    if silver_enabled then
        for _, def in ipairs(silver_defs) do
        core.register_ore({
            ore_type       = "scatter",
            ore            = "moreores:mineral_silver",
            wherein        = "default:stone",
            clust_scarcity = def.s ^ 3,
            clust_num_ores = def.n,
            clust_size     = def.c,
            y_max          = def.y_max,
            y_min          = def.y_min,
        })
        end
    end
end

-- Any ore that is not in this list came from a mod
-- There are mods that alter the definitions of the default ores, but we are
-- going to ignore them for now
-- Note that definitions for nether ores are registered after this, so there is
-- no need to list them here
local yams_base_ores = {
    "default:silver_sandstone",
    "default:desert_sandstone",
    "default:sandstone",
    "default:clay",
    "default:silver_sand",
    "default:dirt",
    "default:gravel",
    "default:stone_with_coal",
    "default:stone_with_tin",
    "default:stone_with_copper",
    "default:stone_with_iron",
    "default:stone_with_gold",
    "default:stone_with_mese",
    "default:stone_with_diamond",
    "default:mese",
    "moreores:mineral_mithril",
    "magic_materials:stone_with_egerum",
    "magic_materials:stone_with_februm",
    "stardust:stone_with_stardust",
}

if silver_enabled then
    table.insert(yams_base_ores, "moreores:mineral_silver")
end

for i=1, #yams_base_ores do
    local name = yams_base_ores[i]
    assert(core.registered_items[name], "typo in yams_mapgen: " .. name)
end

-- Look for ores added by mods and keep track of them
-- This actually fixes a bug in which some ore definitions for the 'nether' mod
-- did not get applied
local additional_ore_defs = {}
for key, def in pairs(core.registered_ores) do
    local ore = def.ore
    if table.indexof(yams_base_ores, ore) == -1 then
        additional_ore_defs[key] = def
    end
end

core.clear_registered_ores()
register_yams_ores()

-- Re-register ore definitions that belong to mods
for key, def in pairs(additional_ore_defs) do
    core.register_ore(def)
end

print("yams_ores loaded")
