----------------------------------------------------------
--IRON WORKING

-- Internationalization
local S = tech.S

----------------------------------------------------------------------
--NODES

--Steps
--this is a simplified version of bloomery furnace method.
--leaves out steps that involve keeping a temporarily hot item in inventory,
--because that is annoying to code e.g. quenching and hammering hot metal

--1: Get ore
--2: crush ore into 'tech:crushed_iron_ore'
--3: roast 'tech:crushed_iron_ore' at wood fire heat into 'tech:roasted_iron_ore'
--4. powder into 'tech:roasted_iron_ore_powder'
--5. mix with x charcoal for 'tech:iron_smelting_mix'
--6. heat to smelt temp to create iron_slag_mix
--7. keep hot enough for X minutes (and a drainage space), for molten slag to run off.
--8. leaves behind small iron bloom (plus cooling slag nearby)
--9. hammer bloom into ingots
--10. make iron anvil out of many ingots
--11. make iron tools at anvil



--------------------------------------

--pre-roast and smelting functions
local function set_roast(pos, length, interval)
	-- and firing count
	local meta = minetest.get_meta(pos)
	meta:set_int("roast", length)
	--check heat interval
	minetest.get_node_timer(pos):start(interval)
end



local function roast(pos, selfname, name, length, heat, smelt)
	local meta = minetest.get_meta(pos)
	local roast = meta:get_int("roast")

	--check if wet stop
	if climate.get_rain(pos) or minetest.find_node_near(pos, 1, {"group:water"}) then
		return true
	end

	--exchange accumulated heat
	climate.heat_transfer(pos, selfname)

	--check if above firing temp
	local temp = climate.get_point_temp(pos)
	local fire_temp = heat

	if roast <= 0 then
		--finished firing
		--need to transfer heat to smelt
		--for others doesn't matter
		if name == "tech:iron_and_slag" then
			temp = meta:get_float("temp")
			minimal.switch_node(pos, {name = name})
			meta:set_float("temp", temp)
			minetest.check_for_falling(pos)
			return false
		else
			minimal.switch_node(pos, {name = name})
			minetest.check_for_falling(pos)
			return false
		end
  elseif temp < fire_temp then
    --not lit yet
    return true
	elseif temp >= fire_temp then
    if smelt then -- #TODO: eliminate directional bias
      --smelting requires release of slag
      --position below
      local posb = {
        {x = pos.x, y = pos.y - 1, z = pos.z},
        {x = pos.x +1, y = pos.y - 1, z = pos.z},
        {x = pos.x -1, y = pos.y - 1, z = pos.z},
        {x = pos.x, y = pos.y - 1, z = pos.z +1},
        {x = pos.x +1, y = pos.y - 1, z = pos.z +1},
        {x = pos.x -1, y = pos.y - 1, z = pos.z +1},
        {x = pos.x, y = pos.y - 1, z = pos.z -1},
        {x = pos.x +1, y = pos.y - 1, z = pos.z -1},
        {x = pos.x -1, y = pos.y - 1, z = pos.z -1}
      }
      local cn = 0
      for _, p in pairs(posb) do
        local n = minetest.get_node(p).name
				--must drain into air or other slag mix
	local target = p
	local tn = n
	if tn == "tech:molten_slag_flowing" then
	   repeat -- add a tail onto existing slag plumes
	      target = vector.add(target, {x = 0, y = -1, z = 0})
	      tn = minetest.get_node(target).name
	   until tn ~= 'tech:molten_slag_flowing'
	end
        if tn == 'air' or tn == 'climate:air_temp' or
	   tn == 'tech:iron_and_slag' then
	   minetest.sound_play("nodes_nature_cool_lava",	{pos = pos, max_hear_distance = 8, gain = 0.1})
	   if tn ~= 'tech:iron_and_slag' then
	      minetest.set_node(target, {name = 'tech:molten_slag_flowing'})
	      --only drain to one place (i.e. so they all drain the same amount)
	      cn = cn + 1
	      break
	   else
	      --undo progress of the one it is draining into.
	      local meta_under = minetest.get_meta(target)
	      local roast_under = meta_under:get_int("roast")
	      --only if still has room (i.e. can't infinitely fill it)
	      if roast_under < 100 then
		 meta_under:set_int("roast", roast_under + 1)
		 --only drain to one place (i.e. so they all drain the same amount)
		 cn = cn + 1
		 break
	      end
	   end
        end
      end
      --only makes smelt progress if able to drain
      if cn > 0 then
        --do firing
        meta:set_int("roast", roast - 1)
        return true
      else
				--try again later
        return true
      end

    else
      --do non-smelting firing
      meta:set_int("roast", roast - 1)
      return true
    end
  end

end






----------------------------

--crushed_iron_ore
--raw ore broken into gravel
minetest.register_node("tech:crushed_iron_ore", {
	description = S("Crushed Iron Ore"),
	tiles = {"tech_crushed_iron_ore.png"},
	stack_max = minimal.stack_max_bulky *2,
	paramtype = "light",
	groups = {crumbly = 3, falling_node = 1, heatable =10},
	sounds = nodes_nature.node_sound_gravel_defaults(),
  on_construct = function(pos)
		--length(i.e. difficulty of firing), interval for checks (speed)
		set_roast(pos, 10, 10)
	end,
	on_timer = function(pos, elapsed)
    --selfname, finished product, length, heat, smelt
    return roast(pos, "tech:crushed_iron_ore", "tech:roasted_iron_ore", 10, 300, false)
	end,
})

--recipe
crafting.register_recipe({
	type = "hammering_block",
	output = "tech:crushed_iron_ore",
	items = {"group:ironstone_cobble 16"},
	level = 1,
	always_known = true,
})

--roasted_iron_ore
--crushed ore pre-roasted
minetest.register_node("tech:roasted_iron_ore", {
	description = S("Roasted Iron Ore"),
	tiles = {"tech_roasted_iron_ore.png"},
	stack_max = minimal.stack_max_bulky *2,
	paramtype = "light",
	groups = {crumbly = 3, falling_node = 1},
	sounds = nodes_nature.node_sound_gravel_defaults(),
})

--roasted iron ore powder
--more smelting prep
minetest.register_node("tech:roasted_iron_ore_powder", {
	description = S("Roasted Iron Ore Powder"),
	tiles = {"tech_roasted_iron_ore_powder.png"},
	stack_max = minimal.stack_max_bulky *4,
	paramtype = "light",
	groups = {crumbly = 3, falling_node = 1},
	sounds = nodes_nature.node_sound_gravel_defaults(),
})

--recipe
crafting.register_recipe({
	type = "hammering_block",
	output = "tech:roasted_iron_ore_powder",
	items = {'tech:roasted_iron_ore 2'},
	level = 1,
	always_known = true,
})

--iron smelting mix
--mix of charcoal blocks and roasted iron ore powder, ready for smelting
--initial heating turns it into slag and iron mix, which continues actual smelt
minetest.register_node("tech:iron_smelting_mix", {
	description = S("Iron Smelting Mix"),
	tiles = {"tech_iron_smelting_mix.png"},
	stack_max = minimal.stack_max_bulky *4,
	paramtype = "light",
	groups = {crumbly = 3, falling_node = 1, heatable = 20},
	sounds = nodes_nature.node_sound_gravel_defaults(),
  on_construct = function(pos)
    --length(i.e. difficulty of firing), interval for checks (speed)
    set_roast(pos, 2, 10)
  end,
  on_timer = function(pos, elapsed)
    --finished product, length, heat, smelt
    return roast(pos, "tech:iron_smelting_mix", "tech:iron_and_slag", 2, 1350, false)
  end,
})

--recipe
crafting.register_recipe({
	type = "hammering_block",
	output = "tech:iron_smelting_mix",
	items = {'tech:roasted_iron_ore_powder', 'tech:charcoal_block 4'},
	level = 1,
	always_known = true,
})

---------------------
--save usage into inventory, to prevent infinite supply
local on_dig_iron_and_slag = function(pos, node, digger)
	if not digger then return end
	if minetest.is_protected(pos, digger:get_player_name()) then
		return false
	end

	local meta = minetest.get_meta(pos)
	local roast = meta:get_int("roast")

	local new_stack = ItemStack("tech:iron_and_slag")
	local stack_meta = new_stack:get_meta()
	stack_meta:set_int("roast", roast)

	minetest.remove_node(pos)
	local player_inv = digger:get_inventory()
	if player_inv:room_for_item("main", new_stack) then
		player_inv:add_item("main", new_stack)
	else
		minetest.add_item(pos, new_stack)
	end
end

--set saved
local after_place_iron_and_slag = function(pos, placer, itemstack, pointed_thing)
	local meta = minetest.get_meta(pos)
	local stack_meta = itemstack:get_meta()
	local roast = stack_meta:get_int("roast")
	if roast >0 then
		meta:set_int("roast", roast)
	end
end

--iron and slag
--unseperated iron and impurities
minetest.register_node("tech:iron_and_slag", {
	description = S("Iron and Slag"),
	tiles = {"tech_iron_and_slag.png"},
	stack_max = minimal.stack_max_bulky,
	paramtype = "light",
	groups = {cracky = 3, crumbly = 1, falling_node = 1, heatable = 20},
	sounds = nodes_nature.node_sound_stone_defaults(),
  on_construct = function(pos)
    --length(i.e. difficulty of firing), interval for checks (speed)
    set_roast(pos, 50, 10)
  end,
  on_timer = function(pos, elapsed)
    --finished product, length, heat, smelt
    return roast(pos, "tech:iron_and_slag", "tech:iron_bloom", 50, 1350, true)
  end,

	on_dig = function(pos, node, digger)
		on_dig_iron_and_slag(pos, node, digger)
	end,
	after_place_node = function(pos, placer, itemstack, pointed_thing)
		after_place_iron_and_slag(pos, placer, itemstack, pointed_thing)
	end,
})


--------------------
--iron bloom
--smelted iron seperated from bulk of slag, but still not useable
minetest.register_node("tech:iron_bloom", {
	description = S("Iron Bloom"),
	tiles = {"tech_iron_and_slag.png"},
  drawtype = "nodebox",
  node_box = {
    type = "fixed",
    fixed = {-0.3, -0.5, -0.3, 0.3, -0.1, 0.3},
  },
	stack_max = minimal.stack_max_bulky * 4,
	paramtype = "light",
	groups = {cracky = 3, falling_node = 1, oddly_breakable_by_hand = 2, temp_pass = 1},
	sounds = nodes_nature.node_sound_stone_defaults(),
})


----------------
--iron ingot
--iron seperated from remainder of slag, finished product
minetest.register_node("tech:iron_ingot", {
	description = S("Iron Ingot"),
	tiles = {"tech_iron.png"},
  drawtype = "nodebox",
	node_box = {
		type = "fixed",
		fixed = {-0.1, -0.5, -0.2, 0.1, -0.3, 0.2},
	},
	stack_max = minimal.stack_max_bulky * 8,
	paramtype = "light",
  paramtype2 = "facedir",
	groups = {falling_node = 1, dig_immediate=3, temp_pass = 1},
	sounds = nodes_nature.node_sound_stone_defaults(),
})

--recipe
crafting.register_recipe({
	type = "hammering_block",
	output = "tech:iron_ingot",
	items = {'tech:iron_bloom 2'},
	level = 1,
	always_known = true,
})

crafting.register_recipe({
	type = "anvil",
	output = "tech:iron_ingot",
	items = {'tech:iron_bloom 2'},
	level = 1,
	always_known = true,
})

-----------------
--slag
--waste product (cooled)
minetest.register_node("tech:slag", {
	description = S("Slag"),
	tiles = {"tech_iron_and_slag.png"},
	stack_max = minimal.stack_max_bulky,
	paramtype = "light",
	groups = {cracky = 3, falling_node = 1, crumbly = 1},
	sounds = nodes_nature.node_sound_stone_defaults(),
})

stairs.register_stair_and_slab(
        "slag",
        "tech:slag",
        "mixing_spot",
        "true",
        {cracky = 3, falling_node = 1, crumbly = 1},
        {"tech_iron_and_slag.png"},
        "Slag Stair",
        "Slag Slab",
        minimal.stack_max_bulky * 8,
        nodes_nature.node_sound_stone_defaults()
)

minetest.override_item("stairs:slab_slag",
                { on_rightclick = function(pos, node, clicker,
                                           itemstack, pointed_thing)
                     return minimal.slabs_combine(pos, node, itemstack, "tech:slag")
                end,
})


--molten slag
local lava_light = 6
local lava_temp_effect = 6
local lava_heater = 1350

minetest.register_node("tech:molten_slag_source", {
	description = S("Molten Slag"),
	drawtype = "liquid",
	tiles = {
		{
			name = "nodes_nature_lava_source_animated.png",
			backface_culling = false,
			animation = {
				type = "vertical_frames",
				aspect_w = 16,
				aspect_h = 16,
				length = 3.0,
			},
		},
		{
			name = "nodes_nature_lava_source_animated.png",
			backface_culling = true,
			animation = {
				type = "vertical_frames",
				aspect_w = 16,
				aspect_h = 16,
				length = 3.0,
			},
		},
	},
	paramtype = "light",
	light_source = lava_light,
	temp_effect = lava_temp_effect,
	temp_effect_max = lava_heater,
	walkable = false,
	pointable = false,
	diggable = false,
	buildable_to = true,
	is_ground_content = false,
	drop = "",
	drowning = 1,
	liquidtype = "source",
	liquid_alternative_flowing = "tech:molten_slag_flowing",
	liquid_alternative_source = "tech:molten_slag_source",
	liquid_viscosity = 7,
	liquid_renewable = false,
	damage_per_second = 4 * 2,
	post_effect_color = {a = 191, r = 255, g = 64, b = 0},
	groups = {igniter = 1, temp_effect = 1},
  --cooling
  on_construct = function(pos)
    minetest.get_node_timer(pos):start(10)
  end,
  on_timer = function(pos, elapsed)
    if math.random()>0.87 then
			minetest.sound_play("nodes_nature_cool_lava",	{pos = pos, max_hear_distance = 8, gain = 0.1})
      minetest.set_node(pos, {name = 'tech:slag'})
			minetest.check_for_falling(pos)
      return false
    else
      return true
    end
  end,
})

minetest.register_node("tech:molten_slag_flowing", {
	description = S("Flowing Molten Slag"),
	drawtype = "flowingliquid",
	tiles = {"nodes_nature_lava.png"},
	special_tiles = {
		{
			name = "nodes_nature_lava_flowing_animated.png",
			backface_culling = false,
			animation = {
				type = "vertical_frames",
				aspect_w = 16,
				aspect_h = 16,
				length = 3.3,
			},
		},
		{
			name = "nodes_nature_lava_flowing_animated.png",
			backface_culling = true,
			animation = {
				type = "vertical_frames",
				aspect_w = 16,
				aspect_h = 16,
				length = 3.3,
			},
		},
	},
	paramtype = "light",
	paramtype2 = "flowingliquid",
	light_source = lava_light,
	temp_effect = lava_temp_effect,
	temp_effect_max = lava_heater,
	walkable = false,
	pointable = false,
	diggable = false,
	buildable_to = true,
	is_ground_content = false,
	drop = "",
	drowning = 1,
	liquidtype = "flowing",
	liquid_alternative_flowing = "tech:molten_slag_flowing",
	liquid_alternative_source = "tech:molten_slag_source",
	liquid_viscosity = 3,
	liquid_renewable = false,
	damage_per_second = 4 * 2,
	post_effect_color = {a = 191, r = 255, g = 64, b = 0},
	groups = {igniter = 1,	not_in_creative_inventory = 1, temp_effect = 1, temp_pass = 1},
  --cooling
  on_construct = function(pos)
    minetest.get_node_timer(pos):start(1)
  end,
  on_timer = function(pos, elapsed)
    if math.random()>0.95 then
			minetest.sound_play("nodes_nature_cool_lava",	{pos = pos, max_hear_distance = 8, gain = 0.1})
      minetest.set_node(pos, {name = 'tech:slag'})
			minetest.check_for_falling(pos)
      return false
    else
      return true
    end
  end,
})


------------------------------------------
--Iron Fittings
-- a catch all item to use in crafts
--e.g. bolts, nails, locks, screws, hinges
--metal content equivalent to enough hinges for one door
minetest.register_craftitem("tech:iron_fittings", {
	description = S("Iron Fittings"),
	inventory_image = "tech_iron_fittings.png",
	stack_max = minimal.stack_max_medium *2,
})


crafting.register_recipe({
	type = "anvil",
	output = "tech:iron_fittings 8",
	items = {'tech:iron_ingot'},
	level = 1,
	always_known = true,
})

--Chest ...see storage
crafting.register_recipe({
	type = "anvil",
	output = "tech:iron_chest",
	items = {'tech:iron_fittings 2', 'tech:iron_ingot 4', 'tech:vegetable_oil'},
	level = 1,
	always_known = true,
})

-- Protection Nails
minetest.register_craftitem("tech:nails", {
        description = S("Protection Nails - Click 3 times"),
        inventory_image = "tech_iron_nails.png",
        stack_max = minimal.stack_max_light,
	on_use = function(itemstack, user, pointed_thing)
	   local istack, playsound = minimal.protection_nail_use(itemstack,
								 user,
								 pointed_thing)
	   if playsound then
	      minetest.sound_play("tech_hammer", { pos = user:get_pos(),
						   gain = 0.15,
						   max_hear_distance=20} )
	   end
	   return istack
	end
})

crafting.register_recipe({
	type = "anvil",
	output = "tech:nails 8",
	items = {'tech:iron_ingot 1',},
	level = 1,
	always_known = true,
})


