local S = core.get_translator(core.get_current_modname())

if core.get_modpath("magic_materials") then
    -- Replace these recipes with easier versions
    core.clear_craft({output = "magic_materials:enchanted_rune"})
    core.clear_craft({output = "magic_materials:enchanted_page"})
    core.clear_craft({output = "magic_materials:enchanted_staff"})

    core.clear_craft({output = "magic_materials:fire_rune"})
    core.clear_craft({output = "magic_materials:ice_rune"})
    core.clear_craft({output = "magic_materials:storm_rune"})
    core.clear_craft({output = "magic_materials:earth_rune"})

    -- Alter this recipe a bit
    core.clear_craft({output = "magic_materials:energy_rune"})

    core.register_craft({
        output = "magic_materials:enchanted_rune",
        recipe = {
            {"", "default:bronze_ingot", ""},
            {"default:bronze_ingot", "magic_materials:egerum_crystal", "default:bronze_ingot"},
            {"", "default:bronze_ingot", ""},
        }
    })

    core.register_craft({
        output = "magic_materials:enchanted_page",
        recipe = {
            {"default:paper", "magic_materials:egerum_crystal"},
        }
    })

    core.register_craft({
        output = "magic_materials:enchanted_staff",
        recipe = {
            {"default:bronze_ingot", "magic_materials:enchanted_rune", "default:bronze_ingot"},
            {"", "default:stick", ""},
            {"", "default:stick", ""},
        }
    })

    core.register_craft({
        output = "magic_materials:fire_rune",
        recipe = {
            {"magic_materials:enchanted_rune", "yams_materials:fire_essence"},
        },
    })

    core.register_craft({
        output = "magic_materials:ice_rune",
        recipe = {
            {"magic_materials:enchanted_rune", "yams_materials:ice_essence"},
        }
    })

    core.register_craft({
        output = "magic_materials:storm_rune",
        recipe = {
            {"yams_materials:water_essence", "magic_materials:enchanted_rune", "yams_materials:wind_essence"},
        }
    })

    core.register_craft({
        output = "magic_materials:earth_rune",
        recipe = {
            {"magic_materials:enchanted_rune", "yams_materials:earth_essence"},
        }
    })

    core.register_craft({
        output = "magic_materials:energy_rune",
        recipe = {
            {"magic_materials:arcanite_crystal", "default:diamond", "magic_materials:arcanite_crystal"},
            {"default:diamond", "magic_materials:enchanted_rune", "default:diamond"},
            {"magic_materials:arcanite_crystal", "default:diamond", "magic_materials:arcanite_crystal"},
        }
    })

    if core.get_modpath("stardust") then
        core.clear_craft({output = "magic_materials:light_rune"})
        core.register_craft({
            output = "magic_materials:light_rune",
            recipe = {
                {"magic_materials:arcanite_crystal", "stardust:stellar_ingot", "magic_materials:arcanite_crystal"},
                {"stardust:stellar_ingot", "magic_materials:enchanted_rune", "stardust:stellar_ingot"},
                {"magic_materials:arcanite_crystal", "stardust:stellar_ingot", "magic_materials:arcanite_crystal"},
            }
        })
    end

    if core.get_modpath("nether") then
        core.clear_craft({output = "magic_materials:void_rune"})
        core.register_craft({
            output = "magic_materials:void_rune",
            recipe = {
                {"magic_materials:arcanite_crystal", "nether:nether_ingot", "magic_materials:arcanite_crystal"},
                {"nether:nether_ingot", "magic_materials:enchanted_rune", "nether:nether_ingot"},
                {"magic_materials:arcanite_crystal", "nether:nether_ingot", "magic_materials:arcanite_crystal"},
            }
        })

        -- Make extra portal books useful, especially since oerkkis can drop
        -- them past a certain depth
        core.register_craft({
            output = "magic_materials:enchanted_page 3",
            recipe = {{"nether:book_of_portals"}}
        })
    end
end

-- Rework the bag recipes to require less grinding and also to lock upgrades
-- behind progression instead of allowing the player to farm 600+ leather
-- without mining at all
if core.get_modpath("sfinv_bags") then
    -- Remove vegan leather from the game first since leather already has
    -- little use and another type of leather is unnecessary
    core.clear_craft({output = "bags:leather"})
    core.unregister_item("bags:leather")

    core.override_item("bags:small", {
        description = S("Small Bag of Holding"),
        _tt_help = S("Adds 8 inventory slots") .. "\n" ..
                   S("Equip in the Bags tab"),
    })

    core.override_item("bags:medium", {
        description = S("Medium Bag of Holding"),
        _tt_help = S("Adds 16 inventory slots") .. "\n" ..
                   S("Equip in the Bags tab"),
    })

    core.override_item("bags:large", {
        description = S("Large Bag of Holding"),
        _tt_help = S("Adds 24 inventory slots") .. "\n" ..
                   S("Equip in the Bags tab"),
    })

    core.override_item("bags:trolley", {
        description = S("Trolley of Holding"),
        -- It's a tool for some reason so make sure there is no way to repair it
        groups = {bagslots = 32, flammable = 2, not_repaired_by_anvil = 1},
        _tt_help = S("Adds 32 inventory slots") .. "\n" ..
                   S("Equip in the Bags tab"),
    })

    if core.get_modpath("farming") and core.get_modpath("mobs")
            and core.get_modpath("magic_materials") then
        core.clear_craft({output = "bags:small"})
        core.clear_craft({output = "bags:medium"})
        core.clear_craft({output = "bags:large"})
        core.clear_craft({output = "bags:trolley"})

        local egerum = "magic_materials:egerum_crystal"

        -- Since inventory space is very important, add two different recipes
        -- for the small bag to make it more likely that the player will
        -- discover how to make the small bag
        core.register_craft({
            output = "bags:small",
            recipe = {
                {egerum, "farming:string", egerum},
                {"mobs:leather", "mobs:leather", "mobs:leather"},
                {"mobs:leather", "mobs:leather", "mobs:leather"}
            }
        })

        core.register_craft({
            output = "bags:small",
            recipe = {
                {egerum, "farming:string", egerum},
                {"group:wool", "group:wool", "group:wool"},
                {"group:wool", "group:wool", "group:wool"}
            }
        })

        local februm = "magic_materials:februm_crystal"
        local gold_ingot = "default:gold_ingot"
        core.register_craft({
            output = "bags:medium",
            recipe = {
                {februm, gold_ingot, februm},
                {gold_ingot, "bags:small", gold_ingot},
                {februm, gold_ingot, februm}
            }
        })

        local arcanite = "magic_materials:arcanite_crystal"
        core.register_craft({
            output = "bags:large",
            recipe = {
                {arcanite, "default:diamond", arcanite},
                {"default:diamond", "bags:medium", "default:diamond"},
                {arcanite, "default:diamond", arcanite}
            }
        })

        local void_rune = "magic_materials:void_rune"
        local mithril_ingot = "moreores:mithril_ingot"
        core.register_craft({
            output = "bags:trolley",
            recipe = {
                {void_rune, mithril_ingot, void_rune},
                {mithril_ingot, "bags:large", mithril_ingot},
                {void_rune, mithril_ingot, void_rune}
            }
        })
    end
end

-- Give some experience for mining ores
local ores = {"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_februm",
              "magic_materials:stone_with_egerum",
              "stardust:stone_with_stardust",
             }

for _, ore_name in ipairs(ores) do
    if core.registered_items[ore_name] then
        core.override_item(ore_name, {
            on_dig = function(pos, node, digger)
                if core.node_dig(pos, node, digger) then
                    local exp = 5 + math.floor(math.abs(pos.y) / 64)
                    yams.add_exp(digger, exp, "digging")
                end
            end
        })
    end
end

-- YAMS-TODO: these two functions should accomodate for mods
local function tree_on_dig(pos, node, digger)
    if core.node_dig(pos, node, digger) and node.param1 == 0 then
        yams.add_exp(digger, 5, "digging")
    end
end

local function tree_on_place(itemstack, placer, pointed_thing)
    -- We need to keep track of this for later
    local old_node_name = core.get_node(pointed_thing.under).name
    local buildable_to = core.registered_nodes[old_node_name].buildable_to

    local before = itemstack:get_count()
    -- Tree blocks call core.rotate_node as their on_place func
    local res = core.rotate_node(itemstack, placer, pointed_thing)
    if before == res:get_count() then
        return res  -- It was not placed
    end
    
    local pos = nil
    if buildable_to then
        -- We are pointing at something like grass so that node got replaced
        -- with the tree block
        pos = pointed_thing.under
    else
        -- We are pointing at a solid node and the tree block replaced air or
        -- a liquid such as water
        pos = pointed_thing.above
    end
    
    local n = core.get_node(pos)
    -- Nodes placed by the player will not give exp when broken
    core.set_node(pos, {name=n.name, param1=1, param2=n.param2})
    return res
end

local function tree_exp_impl()
    for name, def in pairs(core.registered_nodes) do
        if def.groups.tree then
            core.override_item(name, {
                on_dig = tree_on_dig,
                on_place = tree_on_place,
            })
        end
    end
end

core.register_on_mods_loaded(tree_exp_impl)

-- Mark a bunch of items as unrepairable by the anvil
if core.get_modpath("anvil") then
    -- These items do not accumulate wear and never need to be repaired
    if core.get_modpath("orienteering") then
        anvil.make_unrepairable("orienteering:altimeter")
        anvil.make_unrepairable("orienteering:triangulator")
        anvil.make_unrepairable("orienteering:compass")
        anvil.make_unrepairable("orienteering:sextant")
        anvil.make_unrepairable("orienteering:watch")
        anvil.make_unrepairable("orienteering:speedometer")
        anvil.make_unrepairable("orienteering:map")
        anvil.make_unrepairable("orienteering:automapper")
        anvil.make_unrepairable("orienteering:gps")
        anvil.make_unrepairable("orienteering:quadcorder")
    end
    -- Hanggliders are repaired with different methods
    if core.get_modpath("hangglider") then
    	anvil.make_unrepairable("hangglider:hangglider")
    end
    -- Wear works in a special way for flying carpets
    if core.get_modpath("flying_carpet") then
    	anvil.make_unrepairable("flying_carpet:carpet")
    end
    -- Screwdrivers can cause problems with anvils and are not that important
    if core.get_modpath("screwdriver2") then
    	anvil.make_unrepairable("screwdriver2:screwdriver")
    end
end

local tnt_immune = {
    "default:water_source",
    "default:water_flowing",
    "default:river_water_source",
    "default:river_water_flowing",
    "default:lava_source",
    "default:lava_flowing",
    "ebiomes:swamp_water_source",
    "ebiomes:swamp_water_flowing",
    "default:obsidian",
    "caverealms:glow_obsidian",
    "caverealms:glow_obsidian_2",
    "caverealms:glow_obsidian_brick",
    "caverealms:glow_obsidian_brick_2",
    "nether:basalt",
    "nether:basalt_hewn",
    "nether:basalt_chiselled",  -- Used for portal into cloudlands
    "nether:portal",
}

for _, name in ipairs(tnt_immune) do
    if core.registered_items[name] then
        core.override_item(name, {
            on_blast = function() end,
        })
    end
end

if core.get_modpath("mobs") then
    -- Disable meat blocks
    core.clear_craft({output = "mobs:meatblock"})
    core.unregister_item("mobs:meatblock")
    core.clear_craft({output = "mobs:meatblock_raw"})
    core.unregister_item("mobs:meatblock_raw")

    if core.get_modpath("mobs_animal") then
        -- Disable the butter item, which is not used in yams
        core.clear_craft({output = "mobs:butter"})
        core.unregister_item("mobs:butter")

        -- Disable the cheese block item
        core.clear_craft({output = "mobs:cheeseblock"})
        core.unregister_item("mobs:cheeseblock")
        
        if core.get_modpath("bweapons_bows_pack") then
            core.register_craft({
                type = "shaped",
                output = "bweapons_bows_pack:arrow 4",
                recipe = {{"", "default:flint", ""},
                          {"", "default:stick", ""},
                          {"", "mobs:chicken_feather", ""}}
            })
            
            core.register_craft({
                type = "shaped",
                output = "bweapons_bows_pack:bolt 4",
                recipe = {{"", "default:steel_ingot", ""},
                          {"", "default:steel_ingot", ""},
                          {"", "mobs:chicken_feather", ""}}
            })
        end
    end

    -- Rework the net and lasso items as well as their recipes
    core.override_item("mobs:net", {
        description = S("Net"),
        _tt_help = S("Use on tamed animals to obtain them") .. "\n" ..
                   S("Best for smaller animals")
    })

    if core.get_modpath("farming") then
        core.clear_craft({output = "mobs:net"})
        core.register_craft({
            type = "shaped",
            output = "mobs:net",
            recipe = {{"farming:string", "farming:string", "farming:string"},
                      {"farming:string", "farming:string", "farming:string"},
                      {"", "", "default:stick"}}
        })
    end

    core.override_item("mobs:lasso", {
        description = S("Lasso"),
        _tt_help = S("Use on tamed animals to obtain them") .. "\n" ..
                   S("Best for larger animals")
    })

    if core.get_modpath("ropes") then
        core.clear_craft({output = "mobs:lasso"})
        core.register_craft({
            type = "shaped",
            output = "mobs:lasso",
            recipe = {{"", "ropes:ropesegment", "ropes:ropesegment"},
                      {"", "ropes:ropesegment", "ropes:ropesegment"},
                      {"ropes:ropesegment", "", ""}}
        })
    end

    core.override_item("mobs:saddle", {
        _tt_help = S("Place on tamed horses") .. "\n" ..
                   S("Saddled horses can be mounted")
    })

    core.override_item("mobs:shears", {
        description = S("Steel Shears"),
        _tt_help = S("Use on tamed sheep to obtain wool")
    })

    core.override_item("mobs:nametag", {
    	description = S("Name Tag"),
    	_tt_help = S("Use on tamed animals to name them")
    })
end

-- Prevent explosions from affecting HP bars
local hp_bar_def = core.registered_entities["visual_harm_1ndicators:hpbar"]
if hp_bar_def then
    hp_bar_def.on_blast = function()
        return false, false, {}
    end
end

-- If a node's 'buildable_to' field is true, and that node is used to build on
-- the same exact node, it gets consumed even though it replaced the node with
-- itself, which might be unexpected for players
-- One example of this is replacing a flower with itself
-- YAMS-TODO: this is not implemented for nodes with their own on_place
-- YAMS-TODO: placement sound will still play anyway but oh well
local function fix_buildable_to_nodes()
    -- Checks if the node being placed is the same as the node that is there
    local function new_on_place(itemstack, placer, pointed_thing)
        local stack_name = itemstack:get_name()
        if pointed_thing.type == "node" then
            -- If pointing at the flower itself
            local node_under = core.get_node(pointed_thing.under)
            if node_under.name == stack_name then
                return itemstack
            end

            -- If pointing at the node below the flower
            local node_above = core.get_node(pointed_thing.above)
            if node_above.name == stack_name then
                return itemstack
            end
        end

        return core.item_place(itemstack, placer, pointed_thing)
    end

    -- Using core.item_place, as described in the documentation, does not
    -- actually work, so get the 'on_place' callback of a node we know has the
    -- default 'on_place' callback
    local default_on_place = core.registered_nodes["air"].on_place
    for name, def in pairs(core.registered_nodes) do
        if name ~= "air" and name ~= "ignore" then
            if def.buildable_to then
                if def.on_place == default_on_place then
                    core.override_item(name, {
                        on_place = new_on_place
                    })
                else
                    -- Do not bother for now
                    core.log("warning", "fix_buildable_to_nodes: " .. name)
                end
            end
        end
    end
end

core.register_on_mods_loaded(fix_buildable_to_nodes)

-- Disable items that might be reworked in the future
local function disable_items_that_need_rework()
    local items = {
        -- Temporary because this staff is overpowered
        "gadgets_magic:staff_earth",
        -- Temporary because these tomes will be changed
        "gadgets_magic:tome_speed",
        "gadgets_magic:tome_jump",
        "gadgets_magic:tome_gravity",
    }

    for _, name in pairs(items) do
        core.clear_craft({output = name})

        local def = core.registered_items[name]
        core.override_item(name, {
            description = def.description .. " (disabled)",
            on_use = function() return end,
        })
    end
end

core.register_on_mods_loaded(disable_items_that_need_rework)

local function rearrange_sfinv_tabs()
    local desired_order = {
        "sfinv:crafting",
        "craft_lookup:page",
        "creative:all",
        "creative:nodes",
        "creative:tools",
        "creative:craftitems",
        "sfinv_bags:bags",
        "3d_armor:armor",
        "yams_rpg:level_up",
        "awards:awards",
        "sfinv_buttons:buttons",
    }

    if core.get_modpath("sfinv") then
        sfinv.pages_unordered = {}
        for _, key in pairs(desired_order) do
            table.insert(sfinv.pages_unordered, sfinv.pages[key])
        end

        -- Account for other pages added by mods, such as the 'researcher' mod
        for key, data in pairs(sfinv.pages) do
            if table.indexof(desired_order, key) == -1 then
                table.insert(sfinv.pages_unordered, data)
            end
        end
    end
end

core.register_on_mods_loaded(rearrange_sfinv_tabs)
