local coins_per_ingot = 8
local max_components
for i=0,99 do
	if i * coins_per_ingot <= 99 then
		max_components = i
	else break end
end

local u = sorcery.lib
local register_coin = function(metal,gem)
	local m = sorcery.data.metals[metal]
	local g = sorcery.data.gems[gem]
	local desc = (m.desc or metal) .. ' Coin'
	local coinimg = u.image('sorcery_coin.png'):multiply(u.color(m.tone))
	local id = 'sorcery:coin_' .. metal
	if gem then
		desc = (g.desc or gem) .. '-' .. desc
		coinimg = u.image('sorcery_coin_gem.png'):multiply(u.color(g.tone)):blit(coinimg)
		local gemid = id .. '_' .. gem
		minetest.register_craft {
			type = 'shapeless';
			recipe = { 'xdecor:hammer', gemid };
			output = g.parts.shard;
			replacements = {
				{'xdecor:hammer', 'xdecor:hammer'};
				{gemid, id};
			};
		}
		id = gemid
	else
		minetest.register_craft {
			type = 'cooking';
			recipe = id .. ' 2';
			output = m.parts.fragment;
		}
	end

	minetest.register_craftitem(id, {
		description = u.str.capitalize(desc);
		inventory_image = coinimg:render();
		groups = {
			coin = 1; sorcery_coin = 1; metal = 1;
			not_in_creative_inventory = 1;
			-- nice try mr lenin
		};
		_sorcery = {
			material = (gem == nil) and {
				metal = true; id = metal, data = m;
				grindcost = 2, grindvalue = 1;
			} or nil;
		};
	})
end
-- for metal in pairs(sorcery.data.metals) do
sorcery.register.metals.foreach('sorcery:mkcoins',{'sorcery:generate'}, function(metal)
	register_coin(metal)
	-- for gem in pairs(sorcery.data.gems) do
	sorcery.register.gems.foreach('sorcery:mkcoins_' .. metal, {'sorcery:generate'}, function(gem)
		register_coin(metal,gem)
	end)
end)
local update_press_output = function(meta)
	local inv = meta:get_inventory()
	local slot_ingot = inv:get_stack('ingot',1)
	local slot_gem   = inv:get_stack('gem',1)
	local metalname, gemname
	local coincount
	if not inv:is_empty('ingot') then
		local id = slot_ingot:get_name()
		for name,metal in pairs(sorcery.data.metals) do
			if id == metal.parts.ingot then
				metalname = name
				coincount = slot_ingot:get_count()
				goto foundmetal
			end
		end
	end
	inv:set_stack('output',1,ItemStack(nil))
	do return end

	::foundmetal:: if not inv:is_empty('gem') then
		local id = slot_gem:get_name()
		for name,gem in pairs(sorcery.data.gems) do
			if id == gem.parts.item
				then gemname = name
				else goto skip end
			coincount = math.min(coincount, slot_gem:get_count())
			do break end
		::skip::end
	end
	
	coincount = coincount * coins_per_ingot

	local coinname = 'sorcery:coin_' .. metalname ..
		((gemname and '_' .. gemname) or '')

	inv:set_stack('output',1,ItemStack {
		name = coinname;
		count = coincount;
	})
end
do local hitbox = {
	type = 'fixed';
	fixed = {
		-0.5, -0.5, -0.5;
		 0.5,  0.3,  0.5;
	};
} minetest.register_node('sorcery:coin_press', {
	description = "Coin Press";
	drawtype = 'mesh';
	mesh = 'sorcery-coinpress.obj';
	sunlight_propagates = true;
	paramtype = 'light';
	paramtype2 = 'facedir';
	groups = { cracky = 2; oddly_breakable_by_hand = 2; sorcery_metallurgy = 1};
	tiles = {
		'default_wood.png';
		'default_stone.png';
		'default_copper_block.png';
		'default_steel_block.png';
	};
	selection_box = hitbox;
	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		inv:set_size('ingot',1)
		inv:set_size('gem',1)
		inv:set_size('output',1)
		meta:set_string('formspec', [[
			size[8,6]
			list[context;ingot;2,0.5;1,1;]
				image[2,0.5;1,1;sorcery_ingot_outline.png]
			list[context;gem;3,0.5;1,1;]
				image[3,0.5;1,1;sorcery_diamond_outline.png]
			list[context;output;5,0.5;1,1;]
			list[current_player;main;0,2;8,4;]
				listring[context;output]
					listring[current_player;main]
				listring[context;ingot]
					listring[current_player;main]
				listring[context;gem]
					listring[current_player;main]
		]])
	end;
	allow_metadata_inventory_put = function(pos,list,idx,stack,user)
		local id = stack:get_name()
		if list == 'ingot' then
			for name,metal in pairs(sorcery.data.metals) do
				if id == metal.parts.ingot then goto okay end
			end
		elseif list == 'gem' then
			for name,gem in pairs(sorcery.data.gems) do
				if gem.foreign then
					if id == gem.foreign then goto okay end
				else
					if id == 'sorcery:gem_' .. name then goto okay end
				end
			end
		end
		do return 0 end
		::okay:: return max_components
	end;
	-- mercifully there is never any case where moving between the
	-- inventories of the node is allowable
	allow_metadata_inventory_move = function() return 0 end;
	allow_metadata_inventory_take = function(pos,list,idx,stack,user)
		local count = stack:get_count()
		if list == 'output' then
			return (count % coins_per_ingot) == 0 and count or 0
		else return count end
	end;
	on_metadata_inventory_put = function(pos,list,idx,stack,user)
		update_press_output(minetest.get_meta(pos))
	end;
	on_metadata_inventory_take = function(pos,list,idx,stack,user)
		local meta = minetest.get_meta(pos)
		if list == 'output' then
			local items_used = math.floor(stack:get_count() / coins_per_ingot)
			local inv = meta:get_inventory()
			local reduce_slot = function(slot)
				local i = inv:get_stack(slot,1)
				i:take_item(items_used) inv:set_stack(slot,1,i)
			end
			reduce_slot('ingot')
			if not inv:is_empty('gem') then reduce_slot('gem') end
		end
		update_press_output(meta)
	end;
}) end

minetest.register_craft {
	output = 'sorcery:coin_press';
	recipe = {
		{'group:wood','group:wood','group:wood'};
		{'basic_materials:steel_bar','default:steel_ingot','basic_materials:steel_bar'};
		{'default:copper_ingot','default:stone','default:copper_ingot'};
	};
}
