//priority: 900
onEvent('recipes', (event) => {
    materialsToUnify.forEach((material) => {
        let ore = getPreferredItemInTag(Ingredient.of(`#forge:ores/${material}`)).id;
        let block = getPreferredItemInTag(Ingredient.of(`#forge:storage_blocks/${material}`)).id;
        let ingot = getPreferredItemInTag(Ingredient.of(`#forge:ingots/${material}`)).id;
        let nugget = getPreferredItemInTag(Ingredient.of(`#forge:nuggets/${material}`)).id;

        let gem = getPreferredItemInTag(Ingredient.of(`#forge:gems/${material}`)).id;
        let chunk = getPreferredItemInTag(Ingredient.of(`#forge:chunks/${material}`)).id;
        let crushed = getPreferredItemInTag(Ingredient.of(`#create:crushed_ores/${material}`)).id;

        let dust = getPreferredItemInTag(Ingredient.of(`#forge:dusts/${material}`)).id;
        let shard = getPreferredItemInTag(Ingredient.of(`#forge:shards/${material}`)).id;

        let mek_crystal = getPreferredItemInTag(Ingredient.of(`#mekanism:crystals/${material}`)).id;
        let mek_shard = getPreferredItemInTag(Ingredient.of(`#mekanism:shards/${material}`)).id;
        let mek_clump = getPreferredItemInTag(Ingredient.of(`#mekanism:clumps/${material}`)).id;
        let mek_dirty_dust = getPreferredItemInTag(Ingredient.of(`#mekanism:dirty_dusts/${material}`)).id;

        let gear = getPreferredItemInTag(Ingredient.of(`#forge:gears/${material}`)).id;
        let rod = getPreferredItemInTag(Ingredient.of(`#forge:rods/${material}`)).id;
        let plate = getPreferredItemInTag(Ingredient.of(`#forge:plates/${material}`)).id;

        emendatus_item_melting(event, material, ore, block, ingot, nugget, gem, dust, gear, rod, plate);
        emendatus_shapeless_transform(event, material, ore, chunk);
		
		emendatus_ore_chunk_milling(event, material, chunk, crushed)
		emendatus_gem_chunk_milling(event, material, chunk, gem)
		emendatus_dust_chunk_milling(event, material, chunk, dust)
		emendatus_crushed_smelting(event, material, crushed, ingot)
		emendatus_crushed_splashing(event, material)

        mekanism_metal_ore_processing(event, material, ore, mek_crystal, mek_shard, mek_clump, mek_dirty_dust, dust, ingot);
		mekanism_gem_ore_processing(event, material, ore, dust, gem, shard)

        minecraft_dust_smelting(event, material, dust, ingot);

        tconstruct_metal_casting(event, material, block, ingot, nugget, gear, rod, plate);
        tconstruct_gem_casting(event, material, block, gem, gear, rod, plate);
    });

    function emendatus_item_melting(event, material, ore, block, ingot, nugget, gem, dust, gear, rod, plate) {
        let modId;

        blacklistedMaterials = ["coal", "redstone"];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

        if (Fluid.exists(`tconstruct:molten_${material}`)) {
            return
        } else if (Fluid.exists(`emendatusenigmatica:molten_${material}`)) {
            modId = 'emendatusenigmatica';
        } else if (Fluid.exists(`kubejs:molten_${material}`)) {
            modId = 'kubejs';
        } else {
            return;
        }

        let recipes = [],
            fluid = `${modId}:molten_${material}`,
            temp = 9999;

        if (meltingPoints[material]) {
            temp = meltingPoints[material].temp;
        }

        if (block != air) {
            recipes.push({ type: 'block', amount: 1296, input: `forge:storage_blocks/${material}`, time: 171 });
        }
        if (gem != air) {
            recipes.push({ type: 'gem', amount: 144, input: `forge:gems/${material}`, time: 57 });
        }
        if (ingot != air) {
            recipes.push({ type: 'ingot', amount: 144, input: `forge:ingots/${material}`, time: 57 });
        }
        if (dust != air) {
            recipes.push({ type: 'dust', amount: 144, input: `forge:dusts/${material}`, time: 43 });
        }
        if (nugget != air) {
            recipes.push({ type: 'nugget', amount: 16, input: `forge:nuggets/${material}`, time: 19 });
        }
        if (gear != air) {
            recipes.push({ type: 'gear', amount: 576, input: `forge:gears/${material}`, time: 114 });
        }
        if (rod != air) {
            recipes.push({ type: 'rod', amount: 72, input: `forge:rods/${material}`, time: 11 });
        }
        if (plate != air) {
            recipes.push({ type: 'plate', amount: 144, input: `forge:plates/${material}`, time: 80 });
        }

        recipes.forEach((recipe) => {
            event
                .custom({
                    type: 'tconstruct:melting',
                    ingredient: { tag: recipe.input },
                    result: { fluid: fluid, amount: recipe.amount },
                    temperature: temp,
                    time: 43
                })
                .id(`tconstruct:smeltery/melting/metal/${material}/${recipe.type}`);
        });

        if (ore != air && ingot != air) {
            var materialProperties, secondaryFluid;

            try {
                materialProperties = oreProcessingSecondaries[material];
            } catch (err) {
                return;
            }

            if (Fluid.exists(`tconstruct:molten_${materialProperties.secondary}`)) {
                secondaryFluid = `tconstruct:molten_${materialProperties.secondary}`;
            } else if (Fluid.exists(`emendatusenigmatica:molten_${materialProperties.secondary}`)) {
                secondaryFluid = `emendatusenigmatica:molten_${materialProperties.secondary}`;
            } else {
                return;
            }

            event
                .custom({
                    type: 'tconstruct:ore_melting',
                    ingredient: { tag: `forge:ores/${material}` },
                    result: { fluid: fluid, amount: 144 },
                    temperature: temp,
                    time: 98,
                    byproducts: [{ fluid: secondaryFluid, amount: 48 }]
                })
                .id(`tconstruct:smeltery/melting/metal/${material}/ore`);
        }
    }

    function emendatus_shapeless_transform(event, material, ore, chunk) {
        if (ore == air || chunk == air) {
            return;
        }
        if (material == 'mana') {
            material = 'arcane';
        }

        event
            .shapeless(Item.of(`emendatusenigmatica:${material}_chunk`, 4), [`emendatusenigmatica:${material}_cluster`])
            .id(`emendatusenigmatica:chunk_from_cluster/${material}`);
    }

	function emendatus_ore_chunk_milling(event, material, chunk, crushed) {
		if (chunk == air || crushed == air) {
            return;
        }

        blacklistedMaterials = ["diamond", "emerald", "redstone", "quartz"];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

		removeRecipeByID(event, [
			CR(`milling/${material}_ore`),
			CR(`crushing/${material}_ore`)
		])

		event.recipes.createMilling(
			[crushed, Item.of(MU("experience_pearl")).withChance(0.75)],
			chunk
		)
		.processingTime(processingTimesDefault.milling)
		.id(CR(`milling/${material}_chunk`))
	}

	function emendatus_gem_chunk_milling(event, material, chunk, gem) {
		if (chunk == air || gem == air) {
            return;
        }

        blacklistedMaterials = [];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

		event.recipes.createMilling(
			[
				gem,
				Item.of(MU("experience_pearl")).withChance(0.75)
			],
			chunk
		)
		.processingTime(processingTimesDefault.milling)
		.id(CR(`milling/${material}_chunk`))
	}

	function emendatus_dust_chunk_milling(event, material, chunk, dust) {
		if (chunk == air || dust == air) {
            return;
        }

        whitelistedMaterials = ['redstone'];
        for (var i = 0; i < whitelistedMaterials.length; i++) {
            if (whitelistedMaterials[i] != material) {
                return;
            }
        }

		event.recipes.createMilling(
			[
				dust,
				Item.of(MU("experience_pearl")).withChance(0.75)
			],
			chunk
		)
		.processingTime(processingTimesDefault.milling)
		.id(CR(`milling/${material}_chunk`))
	}

	function emendatus_crushed_smelting(event, material, crushed, ingot) {
		if (crushed == air || ingot == air) {
            return;
        }

        blacklistedMaterials = [];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

		removeRecipeByID(event, [
			CR(`smelting/${material}_ingot_from_crushed`),
			CR(`blasting/${material}_ingot_from_crushed`),
			CR(`smelting/ingot_${material}_compat_mekanism`),
			CR(`blasting/ingot_${material}_compat_mekanism`),
		])

		var output = ingot,
		input = CR(`#crushed_ores/${material}`);

        event.smelting(output, input).xp(0.7).id(CR(`smelting/${material}_ingot_from_crushed`));
        event.blasting(output, input).xp(0.7).id(CR(`blasting/${material}_ingot_from_crushed`));
	}

	function emendatus_crushed_splashing(event, material) {
        blacklistedMaterials = [];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

		removeRecipeByID(event, [
			CR(`splashing/crushed_${material}_ore`),
			CR(`splashing/crushed_${material}`),
			CR(`splashing/mekanism/crushed_${material}_ore`),
		])
	}

    function mekanism_metal_ore_processing(
        event,
        material,
        ore,
        mek_crystal,
        mek_shard,
        mek_clump,
        mek_dirty_dust,
        dust,
        ingot
    ) {
        if (ore == air || ingot == air || mek_crystal == air) {
            return;
        }

        blacklistedMaterials = ['copper', 'gold', 'iron'];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

        let mek_dirty_slurry = `emendatusenigmatica:dirty_${material}`,
            mek_clean_slurry = `emendatusenigmatica:clean_${material}`;

        // Dissolution
        event
            .custom({
                type: 'mekanism:dissolution',
                itemInput: { ingredient: { tag: `forge:ores/${material}` } },
                gasInput: { amount: 1, gas: 'mekanism:sulfuric_acid' },
                output: {
                    slurry: mek_dirty_slurry,
                    amount: 1000,
                    chemicalType: 'slurry'
                }
            })
            .id(`mekanism:processing/${material}/slurry/dirty`);

        // Washing
        event
            .custom({
                type: 'mekanism:washing',
                fluidInput: { amount: 5, tag: 'minecraft:water' },
                slurryInput: { amount: 1, slurry: mek_dirty_slurry },
                output: { slurry: mek_clean_slurry, amount: 1 }
            })
            .id(`mekanism:processing/${material}/slurry/clean`);

        // Crystallizing
        event
            .custom({
                type: 'mekanism:crystallizing',
                chemicalType: 'slurry',
                input: { amount: 200, slurry: mek_clean_slurry },
                output: { item: mek_crystal }
            })
            .id(`mekanism:processing/${material}/crystal/from_slurry`);

        // Injecting
        event
            .custom({
                type: 'mekanism:injecting',
                itemInput: { ingredient: { tag: `mekanism:crystals/${material}` } },
                gasInput: { amount: 1, gas: 'mekanism:hydrogen_chloride' },
                output: { item: mek_shard }
            })
            .id(`mekanism:processing/${material}/shard/from_crystal`);
        event
            .custom({
                type: 'mekanism:injecting',
                itemInput: { ingredient: { tag: `forge:ores/${material}` } },
                gasInput: { amount: 1, gas: 'mekanism:hydrogen_chloride' },
                output: { item: mek_shard, count: 4 }
            })
            .id(`mekanism:processing/${material}/shard/from_ore`);

        // Purifying
        event.recipes.mekanism
            .purifying(Item.of(mek_clump), `#mekanism:shards/${material}`, { amount: 1, gas: 'mekanism:oxygen' })
            .id(`mekanism:processing/${material}/clump/from_shard`);
        event.recipes.mekanism
            .purifying(Item.of(mek_clump, 3), `#forge:ores/${material}`, { amount: 1, gas: 'mekanism:oxygen' })
            .id(`mekanism:processing/${material}/clump/from_ore`);

        // Crushing
        event.recipes.mekanism
            .crushing(Item.of(mek_dirty_dust), `#mekanism:clumps/${material}`)
            .id(`mekanism:processing/${material}/dirty_dust/from_clump`);

        // Enriching
        event.recipes.mekanism
            .enriching(Item.of(dust), `#mekanism:dirty_dusts/${material}`)
            .id(`mekanism:processing/${material}/dust/from_dirty_dust`);
        event.recipes.mekanism
            .enriching(Item.of(dust, 2), `#forge:ores/${material}`)
            .id(`mekanism:processing/${material}/dust/from_ore`);
    }
	
	function mekanism_gem_ore_processing(event, material, ore, dust, gem, shard) {
        if (ore == air) {
            return;
        }

        blacklistedMaterials = ['coal'];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

        try {
            var materialProperties = gemProcessingProperties[material],
                count = materialProperties.mekanism.count,
                input = `#forge:ores/${material}`;
        } catch (err) {
            return;
        }

        switch (materialProperties.output) {
            case 'dust':
                output = dust;
                break;
            case 'gem':
                output = gem;
                break;
            case 'shard':
                output = shard;
                break;
            default:
                return;
        }

        event.recipes.mekanism.enriching(Item.of(output, count), input).id(`mekanism:processing/${material}/from_ore`);
    }

    function minecraft_dust_smelting(event, material, dust, ingot) {
        if (ingot == air || dust == air) {
            return;
        }

        blacklistedMaterials = ['starmetal'];

        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

        var output = ingot,
            input = `#forge:dusts/${material}`;

        event.smelting(output, input).xp(0.7);
        event.blasting(output, input).xp(0.7);
    }

    function tconstruct_metal_casting(event, material, block, ingot, nugget, gear, rod, plate) {
        if (ingot == air) {
            return;
        }

        blacklistedMaterials = [];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

        let modId;
        if (Fluid.exists(`tconstruct:molten_${material}`)) {
            modId = 'tconstruct';
        } else if (Fluid.exists(`emendatusenigmatica:molten_${material}`)) {
            modId = 'emendatusenigmatica';
        } else if (Fluid.exists(`kubejs:molten_${material}`)) {
            modId = 'kubejs';
        } else {
            return;
        }

        let recipes = [{ type: 'ingot', amount: 144, cooling: 57, output: ingot }];

        if (nugget != air) {
            recipes.push({ type: 'nugget', amount: 16, cooling: 19, output: nugget });
        }
        if (gear != air) {
            recipes.push({ type: 'gear', amount: 576, cooling: 114, output: gear });
        }
        if (rod != air) {
            recipes.push({ type: 'rod', amount: 72, cooling: 40, output: rod });
        }
        if (plate != air) {
            recipes.push({ type: 'plate', amount: 144, cooling: 57, output: plate });
        }

        let casts = ['gold', 'sand'];
        casts.forEach((cast) => {
            recipes.forEach((recipe) => {
                event
                    .custom({
                        type: 'tconstruct:casting_table',
                        cast: {
                            tag: `tconstruct:casts/${cast == 'sand' ? 'single_use' : 'multi_use'}/${recipe.type}`
                        },
                        cast_consumed: cast == 'sand' ? true : false,
                        fluid: {
                            name: `${modId}:molten_${material}`,
                            amount: recipe.amount
                        },
                        result: recipe.output,
                        cooling_time: recipe.cooling
                    })
                    .id(`tconstruct:smeltery/casting/metal/${material}/${recipe.type}_${cast}_cast`);
            });
        });
        if (block != air) {
            event
                .custom({
                    type: 'tconstruct:casting_basin',
                    fluid: {
                        name: `${modId}:molten_${material}`,
                        amount: 1296
                    },
                    result: block,
                    cooling_time: 171
                })
                .id(`tconstruct:smeltery/casting/metal/${material}/block`);
        }
    }

    function tconstruct_gem_casting(event, material, block, gem, gear, rod, plate) {
        if (gem == air) {
            return;
        }
        let modId;
        if (Fluid.exists(`tconstruct:molten_${material}`)) {
            modId = 'tconstruct';
        } else if (Fluid.exists(`emendatusenigmatica:molten_${material}`)) {
            modId = 'emendatusenigmatica';
        } else if (Fluid.exists(`kubejs:molten_${material}`)) {
            modId = 'kubejs';
        } else {
            return;
        }

        blacklistedMaterials = ['ender', 'coal', "redstone"];
        for (var i = 0; i < blacklistedMaterials.length; i++) {
            if (blacklistedMaterials[i] == material) {
                return;
            }
        }

        if (gem == 'emendatusenigmatica:fluix_gem') {
            gem = Item.of('appliedenergistics2:fluix_crystal', 1)
        }

        let recipes = [{ type: 'gem', amount: 144, cooling: 64, output: gem }];

        if (gear != air) {
            recipes.push({ type: 'gear', amount: 576, cooling: 256, output: gear });
        }
        if (rod != air) {
            recipes.push({ type: 'rod', amount: 72, cooling: 32, output: rod });
        }
        if (plate != air) {
            recipes.push({ type: 'plate', amount: 144, cooling: 64, output: plate });
        }

        let casts = ['gold', 'sand'];
        casts.forEach((cast) => {
            recipes.forEach((recipe) => {
                event
                    .custom({
                        type: 'tconstruct:casting_table',
                        cast: {
                            tag: `tconstruct:casts/${cast == 'sand' ? 'single_use' : 'multi_use'}/${recipe.type}`
                        },
                        cast_consumed: cast == 'sand' ? true : false,
                        fluid: { name: `${modId}:molten_${material}`, amount: recipe.amount },
                        result: recipe.output,
                        cooling_time: recipe.cooling
                    })
                    .id(`tconstruct:smeltery/casting/${material}/${recipe.type}_${cast}_cast`);
            });
        });
        event
            .custom({
                type: 'tconstruct:casting_basin',
                fluid: { name: `${modId}:molten_${material}`, amount: 1296 },
                result: block,
                cooling_time: 193
            })
            .id(`tconstruct:smeltery/casting/${material}/block`);
    }
});
