// Whether or not to unify items in inventory
global["INVENTORY_UNIFY"] = true
// Whether or not to unify items in world
global["ITEM_UNIFY"] = true
// Whether or not to unify recipes
global["RECIPE_UNIFY"] = true
// Whether or not to hide not-first materials in jei (requires secondary script)
global["HIDE_UNIFIED_ITEMS"] = true
// Whether or not to disable non-priority ore-gen
global["UNIFY_ORE_GEN"] = true

// Mod priorities
global["unifypriorities"] = [
    "thermal",
    "mekanism",
    "create",
    "tconstruct",
    "excompressum",
    "exnihilosequentia",
    "immersiveengineering",
    "ironchest",
    "powah",
    "pedestals",
    "titanium",
    "chemlib",
]

// Add oredictionary tags here to unify (or use javascript to generate it!)
var tags = [
    "forge:plates/iron",
    "forge:gears/iron"
]
// Block tags for ore gen unification (an equal item tag is required for this to work, which is the case with ores normally)
/*var btags = [
    "forge:ores/copper",
    "forge:ores/tin",
    "forge:ores/aluminum",
    "forge:ores/lead",
    "forge:ores/silver",
    "forge:ores/nickel",
    "forge:ores/platinum",
    "forge:ores/uranium",
    "forge:ores/iridium",
    "forge:ores/zinc",
    "forge:ores/osmium",
    "forge:ores/sulfur",
]*/
// Easier way to add multiple tags (feel free to add empty extra tags, this will ignore them)
var tagGen = [
    "iron=gears,plates,dusts",
    "gold=gears,plates,dusts",
    "diamond=gears,plates,dusts",
    "copper=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "tin=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "aluminum=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "lead=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "silver=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "nickel=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "bronze=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "steel=ingots,nuggets,dusts",
    "platinum=storage_blocks,ingots,nuggets,dusts,ores",
    "uranium=storage_blocks,ingots,nuggets,dusts,ores",
    "zinc=storage_blocks,ingots,nuggets,dusts,ores",
    "osmium=ingots,ores",
    "sulfur=dusts,ores",
    "electrum=storage_blocks,ingots,nuggets,dusts,ores,gears,plates",
    "constantan=storage_blocks,ingots,nuggets,dusts,ores,gears,plates"
]

var gearsToFix = ["iron", "gold", "diamond", "copper", "tin", "lead", "silver", "nickel", "bronze", "electrum", "invar", "constantan", "signalum", "lumium", "enderium"]

var immersiveGearsToFix = ["signalum", "lumium", "enderium"]

var gearsToCraftMaterials = ['iron', 'diamond', 'gold']

var createPlatesToFix = ["tin", "lead", "silver", "nickel", "bronze", "electrum", "invar", "constantan", "signalum", "lumium", "enderium"]

for (let line of tagGen) {
    let data = line.split("=")
    for (let type of data[1].split(",")) {
        tags.push("forge:" + type + "/" + data[0])
    }
}

// Replace input and output of recipes (and iterate over tags!)
onEvent("recipes", event => {
    // Iterate over tags (they should be loaded)
    var tagitems = new Map()
    tagLoop:
    for (let tag of tags) {
        let ingr = Ingredient.of("#"+tag)
        if (ingr) {
            let stacks = ingr.getStacks().toArray()
            for (let mod of global["unifypriorities"]) {
                for (let stack of stacks) {
                    if (stack.getMod() == mod) {
                        tagitems[tag] = stack.getId()
                        continue tagLoop
                    }
                }
            }
            if (stacks.length > 0) tagitems[tag] = stacks[0].getId()
        }
    }
    // Update tags
    global["unifytags"] = tags
    global["tagitems"] = tagitems
    
    // Unify the rest
    if (global["RECIPE_UNIFY"]) {
        for (let tag of global["unifytags"]) {
            let ingr = Ingredient.of("#"+tag)
            if (ingr) {
                let stacks = ingr.getStacks().toArray()
                let oItem = global["tagitems"][tag]
                for (let tItem of stacks) {
                    event.replaceInput({}, tItem.getId(), "#"+tag)
                    event.replaceOutput({}, tItem.getId(), oItem)
                }
            }
        }
    }

    event.remove({id: 'immersiveengineering:crafting/ingot_steel_to_storage_steel'})

    event.remove({output: 'immersiveengineering:slab_storage_steel'})
    event.shaped('immersiveengineering:slab_storage_steel', [
        'SSS'
    ], {
        S: 'mekanism:block_steel'
    })

    gearsToCraftMaterials.forEach(gearsMaterial => {
        event.remove({output: `thermal:${gearsMaterial}_gear`, id: `industrialforegoing:${gearsMaterial}_gear`})
    })

    event.recipes.immersiveengineeringMetalPress(`thermal:diamond_gear`, `4x minecraft:diamond`, 'immersiveengineering:mold_gear')

    gearsToFix.forEach(gear => {
        event.remove({id: `thermal:parts/${gear}_gear`})
    })

    event.recipes.thermal.press('thermal:diamond_gear', ['4x minecraft:diamond', 'thermal:press_gear_die'])

    immersiveGearsToFix.forEach(gear => {
        event.recipes.immersiveengineeringMetalPress(`thermal:${gear}_gear`, `4x thermal:${gear}_ingot`, 'immersiveengineering:mold_gear')
    })

    event.remove({id: `pneumaticcraft:compressed_iron_gear`})
    event.recipes.thermal.press('pneumaticcraft:compressed_iron_gear', ['4x pneumaticcraft:ingot_iron_compressed', 'thermal:press_gear_die'])
    event.recipes.immersiveengineeringMetalPress('pneumaticcraft:compressed_iron_gear', `4x pneumaticcraft:ingot_iron_compressed`, 'immersiveengineering:mold_gear')

    createPlatesToFix.forEach(plate => {
        event.recipes.createPressing(`thermal:${plate}_plate`, `thermal:${plate}_ingot`)
    })

    event.recipes.createPressing('thermal:netherite_plate', 'minecraft:netherite_ingot')
    event.recipes.immersiveengineeringMetalPress('thermal:netherite_plate', 'minecraft:netherite_ingot', 'immersiveengineering:mold_plate')
    
    event.recipes.thermal.press('createaddition:zinc_sheet', 'create:zinc_ingot')
    event.recipes.thermal.press('create:brass_sheet', 'create:brass_ingot')
})

// Handle inventory change (to check for unificaiton)
// Unfortunately it gets called twice due to setting the inventory.
onEvent("player.inventory.changed", event => {
    if (global["INVENTORY_UNIFY"] && event.getEntity().getOpenInventory().getClass().getName() == "net.minecraft.inventory.container.PlayerContainer") {
        // Get held item
        var heldItem = event.getItem()
        
        // Check for every tag in the list
        for (let tag of global["unifytags"]) {
            let ingr = Ingredient.of("#"+tag)
            if (ingr.test(heldItem)) {
                // If item is in tag, determine if it needs to be changed
                let tItem = global["tagitems"][tag]
                if (tItem != heldItem.getId()) {
                    // Fix slot number
                    let slot = event.getSlot()
                    if (slot <= 5) slot += 36
                    else if (slot == 45) slot = 40
                    else if (slot >= 36) slot -= 36
                    // Update item
                    event.getEntity().inventory.set(slot, Item.of(tItem, heldItem.getCount()))
                }
                break
            }
        }
    }
})

// Items on ground
/*onEvent("entity.spawned", event => {
    if (global["ITEM_UNIFY"]) {
        var entity = event.getEntity()
        if (entity.getType() == "minecraft:item") {
            var gItem = entity.getItem()
            // Check for every tag in the list
            for (let tag of global["unifytags"]) {
                let ingr = Ingredient.of("#"+tag)
                if (ingr && ingr.test(gItem)) {
                    // If item is in tag, determine if it needs to be changed
                    let tItem = global["tagitems"][tag]
                    if (tItem != gItem.getId()) {
                        entity.setItem(Item.of(tItem, gItem.getCount()))
                    }
                    break
                }
            }
        }
    }
})*/