-- IndustrialTest
-- Copyright (C) 2023 mrkubax10

-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.

-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

local S=minetest.get_translator("industrialtest")
industrialtest.IronFurnace=table.copy(industrialtest.ActivatedMachine)
industrialtest.internal.unpackTableInto(industrialtest.IronFurnace,{
	name="industrialtest:iron_furnace",
	description=S("Iron Furnace"),
	tiles={
		"industrialtest_machine_block.png",
		"industrialtest_machine_block.png",
		"industrialtest_machine_block.png",
		"industrialtest_machine_block.png",
		"industrialtest_machine_block.png",
		"industrialtest_machine_block.png^industrialtest_iron_furnace_front.png",
		"industrialtest_machine_block.png"
	},
	active={
		tiles={
			"industrialtest_machine_block.png",
			"industrialtest_machine_block.png",
			"industrialtest_machine_block.png",
			"industrialtest_machine_block.png",
			"industrialtest_machine_block.png",
			"industrialtest_machine_block.png^industrialtest_iron_furnace_front_active.png",
			"industrialtest_machine_block.png"
		},
		lightSource=8
	},
	facedir=true,
	storageLists={
		"src",
		"fuel",
		"dst"
	}
})

function industrialtest.IronFurnace.onConstruct(self,pos)
	local meta=minetest.get_meta(pos)
	local inv=meta:get_inventory()
	inv:set_size("src",1)
	inv:set_size("dst",1)
	inv:set_size("fuel",1)
	meta:set_float("fuelTime",0)
	meta:set_float("maxFuelTime",1)
	meta:set_float("srcTime",0)
	meta:set_float("maxSrcTime",0)
	industrialtest.ActivatedMachine.onConstruct(self,pos)
end

function industrialtest.IronFurnace.getFormspec(self,pos)
	local parentFormspec=industrialtest.ActivatedMachine.getFormspec(self,pos)
	local meta=minetest.get_meta(pos)
	local fuelPercent=meta:get_float("fuelTime")/meta:get_float("maxFuelTime")*100
	local maxSrcTime=meta:get_float("maxSrcTime")
	local srcPercent=meta:get_float("srcTime")/(maxSrcTime>0 and maxSrcTime or 0)*100
	local formspec
	if industrialtest.mtgAvailable then
		formspec={
			"list[context;src;3.4,1.8;1,1]",
			(fuelPercent>0 and "image[3.4,2.8;1,1;default_furnace_fire_bg.png^[lowpart:"..fuelPercent..":default_furnace_fire_fg.png]"
			 or "image[3.4,2.8;1,1;default_furnace_fire_bg.png]"),
			"list[context;fuel;3.4,3.9;1,1]",
			(srcPercent>0 and "image[4.9,2.8;1,1;gui_furnace_arrow_bg.png^[lowpart:"..srcPercent..":gui_furnace_arrow_fg.png^[transformR270]"
			 or "image[4.9,2.8;1,1;gui_furnace_arrow_bg.png^[transformR270]"),
			"list[context;dst;6.4,2.8;1,1]",
			"listring[context;src]",
			"listring[context;dst]"
		}
	elseif industrialtest.mclAvailable then
		formspec={
			"list[context;src;3.4,1.8;1,1]",
			mcl_formspec.get_itemslot_bg(3.4,1.8,1,1),
			(fuelPercent>0 and "image[3.4,2.8;1,1;default_furnace_fire_bg.png^[lowpart:"..fuelPercent..":default_furnace_fire_fg.png]"
			 or "image[3.4,2.8;1,1;default_furnace_fire_bg.png]"),
			"list[context;fuel;3.4,3.9;1,1]",
			mcl_formspec.get_itemslot_bg(3.4,3.9,1,1),
			(srcPercent>0 and "image[4.9,2.8;1,1;gui_furnace_arrow_bg.png^[lowpart:"..srcPercent..":gui_furnace_arrow_fg.png^[transformR270]"
			 or "image[4.9,2.8;1,1;gui_furnace_arrow_bg.png^[transformR270]"),
			"list[context;dst;6.4,2.8;1,1]",
			mcl_formspec.get_itemslot_bg(6.4,2.8,1,1),
			"listring[context;src]",
			"listring[context;dst]"
		}
	end
	return parentFormspec..table.concat(formspec,"")
end

function industrialtest.IronFurnace.allowMetadataInventoryMove(self,pos,fromList,fromIndex,toList,toIndex,count)
	if toList=="dst" then
		return 0
	end
	return industrialtest.ActivatedMachine.allowMetadataInventoryMove(self,pos,fromList,fromIndex,toList,toIndex,count)
end

function industrialtest.IronFurnace.allowMetadataInventoryPut(self,pos,listname,index,stack)
	if listname=="dst" then
		return 0
	elseif listname=="src" then
		local meta=minetest.get_meta(pos)
		local inv=meta:get_inventory()
		local srcSlot=inv:get_stack("src",1)
		if srcSlot:get_name()~=stack:get_name() then
			meta:set_float("srcTime",0)
			meta:set_float("maxSrcTime",0)
		end
	end
	return industrialtest.ActivatedMachine.allowMetadataInventoryPut(self,pos,listname,index,stack)
end

function industrialtest.IronFurnace.allowMetadataInventoryTake(self,pos,listname,index,stack)
	local meta=minetest.get_meta(pos)
	local inv=meta:get_inventory()
	local srcSlot=inv:get_stack("src",1)
	local dstSlot=inv:get_stack("dst",1)
	if listname=="src" and stack:get_count()==srcSlot:get_count() then
		meta:set_float("srcTime",0)
		meta:set_float("maxSrcTime",0)
		if meta:get_float("maxFuelTime")>0 then
			self:updateFormspec(pos)
		end
	elseif listname=="dst" and dstSlot:get_free_space()==0 then
		minetest.get_node_timer(pos):start(industrialtest.updateDelay)
	end
	return industrialtest.ActivatedMachine.allowMetadataInventoryTake(self,pos,listname,index,stack)
end

function industrialtest.IronFurnace.onMetadataInventoryMove(self,pos,fromList,fromIndex,toList,toIndex,count)
	local meta=minetest.get_meta(pos)
	local inv=meta:get_inventory()
	local srcSlot=inv:get_stack("src",1)
	local dstSlot=inv:get_stack("dst",1)
	if fromList=="src" and count==srcSlot:get_count() then
		meta:set_float("srcTime",-1)
		meta:set_float("maxSrcTime",0)
		if meta:get_float("maxFuelTime")>0 then
			self:updateFormspec(pos)
		end
	elseif fromList=="dst" and dstSlot:get_free_space()==0 then
		minetest.get_node_timer(pos):start(industrialtest.updateDelay)
	end
	industrialtest.ActivatedMachine.onMetadataInventoryMove(self,pos,fromList,fromIndex,toList,toIndex,count)
end

function industrialtest.IronFurnace.onMetadataInventoryPut(self,pos,listname,index,stack)
	minetest.get_node_timer(pos):start(industrialtest.updateDelay)
	industrialtest.ActivatedMachine.onMetadataInventoryPut(self,pos,listname,index,stack)
end

function industrialtest.IronFurnace.activeUpdate(self,pos,elapsed,meta,inv)
	local srcSlot=inv:get_stack("src",1)
	local fuelSlot=inv:get_stack("fuel",1)
	local shouldUpdateFormspec=false
	local shouldRerunTimer=false

	if fuelSlot:get_count()>0 and meta:get_float("fuelTime")<=0 then
		local output,after=minetest.get_craft_result({
			method="cooking",
			width=1,
			items={srcSlot}
		})
		if output.time>0 and inv:room_for_item("dst",output.item) then
			output,after=minetest.get_craft_result({
				method="fuel",
				width=1,
				items={fuelSlot}
			})
			if output.time>0 then
				meta:set_float("fuelTime",output.time)
				meta:set_float("maxFuelTime",output.time)
				inv:set_stack("fuel",1,after.items[1])
			end
		end
	end
	if srcSlot:get_count()>0 and meta:get_float("maxSrcTime")<=0 and meta:get_float("fuelTime")>0 then
		local output,after=minetest.get_craft_result({
			method="cooking",
			width=1,
			items={srcSlot}
		})
		if output.time>0 and inv:room_for_item("dst",output.item) then
			meta:set_float("srcTime",0)
			meta:set_float("maxSrcTime",output.time*0.7)
		end
	end
	if meta:get_float("fuelTime")>0 then
		if meta:get_float("maxSrcTime")>0 then
			meta:set_float("srcTime",meta:get_float("srcTime")+elapsed)
		end
		meta:set_float("fuelTime",meta:get_float("fuelTime")-elapsed)
		shouldUpdateFormspec=true
		shouldRerunTimer=true
	end
	if meta:get_float("srcTime")>=meta:get_float("maxSrcTime") then
		local output,after=minetest.get_craft_result({
			method="cooking",
			width=1,
			items={srcSlot}
		})
		if output.item:get_count()>0 then
			inv:set_stack("src",1,after.items[1])
			inv:add_item("dst",output.item)
			meta:set_float("srcTime",-1)
			meta:set_float("maxSrcTime",0)
		end
	end

	return shouldRerunTimer,shouldUpdateFormspec
end

function industrialtest.IronFurnace.shouldActivate(self,pos)
	local meta=minetest.get_meta(pos)
	local inv=meta:get_inventory()
	local fuelSlot=inv:get_stack("fuel",1)
	if fuelSlot:get_count()>0 then
		local srcSlot=inv:get_stack("src",1)
		local output,after=minetest.get_craft_result({
			method="cooking",
			width=1,
			items={srcSlot}
		})
		if output.time>0 and inv:room_for_item("dst",output.item) then
			output,after=minetest.get_craft_result({
				method="fuel",
				width=1,
				items={fuelSlot}
			})
			if output.time>0 then
				meta:set_float("fuelTime",output.time)
				meta:set_float("maxFuelTime",output.time)
				inv:set_stack("fuel",1,after.items[1])
				return true
			end
		end
	end
	return false
end

function industrialtest.IronFurnace.shouldDeactivate(self,pos)
	local meta=minetest.get_meta(pos)

	if meta:get_float("fuelTime")>0 then
		return false
	end

	local inv=meta:get_inventory()

	local srcSlot=inv:get_stack("src",1)
	local srcOutput,_=minetest.get_craft_result({
		method="cooking",
		width=1,
		items={srcSlot}
	})
	if srcOutput.time==0 or not inv:room_for_item("dst",srcOutput.item) then
		meta:set_float("srcTime",0)
		return true
	end
	
	local fuelSlot=inv:get_stack("fuel",1)
	local fuelOutput,_=minetest.get_craft_result({
		method="fuel",
		width=1,
		items={fuelSlot}
	})
	if fuelOutput.time==0 then
		meta:set_float("srcTime",0)
		return true
	end

	return false
end

function industrialtest.IronFurnace.afterDeactivation(self,pos)
	self:updateFormspec(pos)
end

industrialtest.IronFurnace:register()

minetest.register_craft({
	type="shaped",
	output="industrialtest:iron_furnace",
	recipe={
		{industrialtest.elementKeys.ironIngot,industrialtest.elementKeys.ironIngot,industrialtest.elementKeys.ironIngot},
		{industrialtest.elementKeys.ironIngot,"",industrialtest.elementKeys.ironIngot},
		{industrialtest.elementKeys.ironIngot,industrialtest.elementKeys.ironIngot,industrialtest.elementKeys.ironIngot}
	}
})
minetest.register_craft({
	type="shaped",
	output="industrialtest:iron_furnace",
	recipe={
		{"",industrialtest.elementKeys.ironIngot,""},
		{industrialtest.elementKeys.ironIngot,"",industrialtest.elementKeys.ironIngot},
		{industrialtest.elementKeys.ironIngot,industrialtest.elementKeys.furnace,industrialtest.elementKeys.ironIngot}
	}
})