local NAME = minetest.get_current_modname()
local modifier = 10 -- Cooking cost modifier
local time_modifier = 3 -- Cooking time modifier
local CAPACITY = 200
local FUEL_MULTIPLIER = 1.5

local formspec_no_energy = sparktech.add_inventory(6,3,
	"list[current_name;source;0,0;2,1;]" ..
	"list[current_name;fuel;1.25,1.25;2,1;]" ..
	"list[current_name;product;2.5,0;2,1;]")

local formspec_energy = sparktech.add_inventory(6,3,
	"image[0,2.5;9.375,0.25;energy2.png]" ..
	"list[current_name;source;0,0;2,1;]" ..
	"list[current_name;fuel;1.25,1.25;2,1;]" ..
	"list[current_name;product;2.5,0;2,1;]")

local function is_fuel(items)
	local fuel
	local afterfuel
	fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = items})
	return fuel["time"] ~= 0
end

local function is_smeltable(items)
	if not items then return false end
	local cooked, _
	cooked, _ = minetest.get_craft_result(
	{method = "cooking", width = 1, items = items})
	return cooked.time ~= 0
end

local function is_item_allowed(pos, target, _, stack)
	if target == "fuel" and is_fuel({stack}) ~= 0 then
        return stack:get_count()
	end
	if target ~= "source" then return 0 end

	if not is_smeltable({stack}) then
		return 0
	else
		return stack:get_count()
	end
end

local function is_item_allowed_move(pos, src, sidx, target, tidx, c, p)
	local meta = minetest.get_meta(pos)
	local inv = meta:get_inventory()
	local stack = inv:get_stack(src, sidx)
	return is_item_allowed(pos, target, tidx, stack, p)
end

local function ongetitem(pos)
	local meta = minetest.get_meta(pos)
	if meta:get_int("energy") < modifier then return end
	local timer = minetest.get_node_timer(pos)
	timer:start(1.0)
end

local function blast_furnace_timer(pos, elapsed)
	local meta = minetest.get_meta(pos)
	local fenergy = meta:get_int("fenergy")
	local inventory = meta:get_inventory()

    if  minetest.get_node({ x= pos.x +1, y=pos.y, z=pos.z })["name"] == NAME .. ":active_bag" or
        minetest.get_node({ x= pos.x -1, y=pos.y, z=pos.z })["name"] == NAME .. ":active_bag" or
        minetest.get_node({ x= pos.x, y=pos.y, z=pos.z +1 })["name"] == NAME .. ":active_bag" or
        minetest.get_node({ x= pos.x, y=pos.y, z=pos.z -1 })["name"] == NAME .. ":active_bag" then
    else
		return false
	end

    if fenergy <= CAPACITY then
		local fuel_energy = meta:get_int("_fuel_energy")
			if fuel_energy > 0 then
				local change
				if fuel_energy > 5 then
					change = 5
				else
					change = fuel_energy
				end
				meta:set_int("_fuel_energy", meta:get_int("_fuel_energy") - change)
				if (fenergy + change >= CAPACITY) then
					fenergy = CAPACITY
					meta:set_int("fenergy", CAPACITY)
				else
					fenergy = fenergy + change
					meta:set_int("fenergy", fenergy + change)
				end
			else
				local fuelitem = {inventory:get_stack("fuel", 1)}
				local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuelitem})
				if fuel["time"] ~= 0 then
					inventory:set_stack("fuel", 1, afterfuel["items"][1])
					local fuel_energy = fuel["time"] * FUEL_MULTIPLIER
					meta:set_int("_fuel_energy", fuel_energy)
				end
		end
	end

	if fenergy >= modifier then
		local cooked
		local aftercooked
		local progress = meta:get_int("progress_" .. 1)
		cooked, aftercooked = minetest.get_craft_result(
			{method = "cooking", width = 1, items = 
				{inventory:get_stack("source", 1)}})
		if progress >= math.ceil(cooked.time * time_modifier) then
			if inventory:room_for_item("product", cooked.item) then
				inventory:add_item("product", cooked.item)
				inventory:set_stack("source", 1, aftercooked.items[1])
				meta:set_int("progress_" .. 1, 0)
			end
		else
			meta:set_int("progress_" .. 1, progress + 1)
			fenergy = fenergy - modifier
		end
	end

	-- named fenergy and not energy so sparktech doesn't try to pull it
	-- it shouldn't since it's not a sparktech node, but just to be safe
	meta:set_int("fenergy", fenergy)
	
	if fenergy > 1 then
		meta:set_string("formspec", formspec_energy)
	else
		meta:set_string("fomspec", formspec_no_energy)
	end

	if fenergy <= CAPACITY and not inventory:get_stack("fuel", 1):is_empty() then
		return true -- we have fuel to burn and can store it
	end

	if not inventory:get_stack("source", 1):is_empty() and fenergy > 1 or not inventory:get_stack("fuel", 1):is_empty() then
		return true -- we have fuel or energy and items to burn
	end
	return false
end

minetest.register_node( NAME .. ":inactive_bag", {
	description = "air bag (for furnace)",
	tiles = { NAME .. "_inactive_bag.png" },
	on_punch = function(pos)
		minetest.swap_node(pos, { name = NAME .. ":active_bag" })
		minetest.get_node_timer(pos):set(7, 0)
		minetest.get_node_timer(pos):start(7.0)
		for x=-1,1,2 do
			local position = { x = pos.x + x, y = pos.y, z = pos.z }
			local node = minetest.get_node(position)
			if node["name"] == NAME .. ":blast_furnace" then
				minetest.get_node_timer(position):start(1.0)
			end
		end
		for z=-1,1,2 do
			local position = { x = pos.x, y = pos.y, z = pos.z + z }
			local node = minetest.get_node(position)
			if node["name"] == NAME .. ":blast_furnace" then
				minetest.get_node_timer(position):start(1.0)
			end
		end
	end
})

minetest.register_node( NAME .. ":active_bag", {
	description = "air bag (for furnace)",
	tiles = { NAME .. "_active_bag.png" },
	on_rightclick = function(pos)
		minetest.get_node_timer(pos):set(7, 0)
		minetest.get_node_timer(pos):start(7.0)
	end,
	on_punch = function(pos)
		minetest.get_node_timer(pos):set(7, 0)
		minetest.get_node_timer(pos):start(7.0)
	end,
	on_construct = function(pos)
        minetest.swap_node(pos, { name = NAME .. ":inactive_bag"})
	end,
	on_timer = function(pos)
        minetest.swap_node(pos, { name = NAME .. ":inactive_bag"})
	end
})

minetest.register_node( NAME .. ":blast_furnace", {
	description = "Blast furnace",

	tiles = {
		NAME .. "_blast_furnace_side.png",
		NAME .. "_blast_furnace_side.png",
		NAME .. "_blast_furnace_side.png",
		NAME .. "_blast_furnace_side.png",
		NAME .. "_blast_furnace_back.png",
		NAME .. "_blast_furnace_front.png"
	},
	paramtype2 = "facedir",

	on_timer = blast_furnace_timer,

	on_construct = function(pos, placer)
		local meta = minetest.get_meta(pos)
		meta:set_string("formspec", formspec_no_energy)
		local inventory = meta:get_inventory()
		inventory:set_size('source', 1)
		inventory:set_size('product', 1)
		inventory:set_size('fuel', 1)
	end,

	allow_metadata_inventory_put = is_item_allowed,
	allow_metadata_inventory_move = is_item_allowed_move,
	on_metadata_inventory_put = ongetitem
})

minetest.register_craft({
        output = NAME .. ":blast_furnace",
        recipe = {
                { "", "orionworld:stone", "" },
                { "orionworld:stone", "", "orionworld:stone" },
                { "orionworld:stone", "orionworld:stone", "orionworld:stone" }
        }
})

minetest.register_craft({
        output = NAME .. ":inactive_bag",
        recipe = {
                { "orionworld:stone", "orionworld:stone", "orionworld:stone" },
                { "orioncraft:rope", "", "orioncraft:rope" },
                { "orionworld:stone", "orionworld:stone", "orionworld:stone" }
        }
})
