local lib = starsoul.mod.lib
local W = starsoul.world
local M = W.material

M.element.foreach('starsoul:sort', {}, function(id, m)
	if m.metal then
		M.metal.link(id, {
			name = m.name;
			composition = starsoul.type.fab{element = {[id] = 1}};
			color = m.color;
			-- n.b. this is a RATIO: it will be appropriately multiplied
			-- for the object in question; e.g a normal chunk will be
			-- 100 $element, an ingot will be 1000 $element
		})
	elseif m.gas then
		M.gas.link(id, {
			name = m.name;
			composition = starsoul.type.fab{element = {[id] = 1}};
		})
	elseif m.liquid then
		M.liquid.link(id, {
			name = m.name;
			composition = starsoul.type.fab{element = {[id] = 1}};
		})
	end
end)

local F = string.format

local function mkEltIndicator(composition)
	local indicator = ''
	local idx = 0
	local ccount = 0
	for _ in pairs(composition) do
		ccount = ccount + 1
	end
	local indsz,indpad = 28,4
	local ofs = math.min(11, (indsz-indpad)/ccount)
	for id, amt in pairs(composition) do
		idx = idx + 1
		indicator = indicator .. F(
			':%s,3=starsoul-element-%s.png',
			(indsz-indpad) - (idx*ofs), id
		)
	end
	indicator = lib.image(indicator)
	return function(s)
		return string.format('(%s^[resize:%sx%s)^[combine:%sx%s%s',
			s,
			indsz, indsz,
			indsz, indsz,
			indicator);
	end
end

M.element.foreach('starsoul:gen-forms', {}, function(id, m)
	local eltID = F('%s:element_%s', minetest.get_current_modname(), id)
	local eltName = F('Elemental %s', lib.str.capitalize(m.name))
	local tt = function(t, d, g)
		return starsoul.ui.tooltip {
			title = t, desc = d;
			color = lib.color(0.1,0.2,0.1);
			props = {
				{title = 'Mass', desc = lib.math.si('g', g), affinity='info'}
			}
		}
	end
	local comp = {[id] = 1}
	local iblit = mkEltIndicator(comp)
	m.form = m.form or {}
	m.form.element = eltID

	local powder = F('starsoul-element-%s-powder.png', id);
	minetest.register_craftitem(eltID, {
		short_description = eltName;
		description = tt(eltName, F('Elemental %s kept in suspension by a nanide storage system, ready to be worked by a cold matter compiler', m.name), 1);
		inventory_image = iblit(powder);
		wield_image = powder;
		stack_max = 1000; -- 1kg
		groups = {element = 1, powder = 1, specialInventory = 1};
		_starsoul = {
			mass = 1;
			material = {
				kind = 'element';
				element = id;
			};
			fab = starsoul.type.fab {
				element = comp;
			};
		};
	});
end)


M.metal.foreach('starsoul:gen-forms', {}, function(id, m)
	local baseID = F('%s:metal_%s_', minetest.get_current_modname(), id)
	local brickID, ingotID = baseID .. 'brick', baseID .. 'ingot'
	local brickName, ingotName =
		F('%s Brick', lib.str.capitalize(m.name)),
		F('%s Ingot', lib.str.capitalize(m.name))
	m.form = m.form or {}
	m.form.brick = brickID
	m.form.ingot = ingotID
	local tt = function(t, d, g)
		return starsoul.ui.tooltip {
			title = t, desc = d;
			color = lib.color(0.1,0.1,0.1);
			props = {
				{title = 'Mass', desc = lib.math.si('g', g), affinity='info'}
			}
		}
	end
	local mcomp = m.composition:elementalize().element
	local function comp(n)
		local t = {}
		for id, amt in pairs(mcomp) do
			t[id] = amt * n
		end
		return t
	end
	local iblit = mkEltIndicator(mcomp)
	local function img(s)
		return iblit(s:colorize(m.color):render())
	end

	minetest.register_craftitem(brickID, {
		short_description = brickName;
		description = tt(brickName, F('A solid brick of %s, ready to be worked by a matter compiler', m.name), 100);
		inventory_image = img(lib.image 'starsoul-item-brick.png');
		wield_image = lib.image 'starsoul-item-brick.png':colorize(m.color):render();
		stack_max = 10;
		groups = {metal = 1, ingot = 1};
		_starsoul = {
			mass = 100;
			material = {
				kind = 'metal';
				metal = id;
			};
			fab = starsoul.type.fab {
				flag = {smelt= true};
				element = comp(1e2);
			};
		};
	});

	minetest.register_craftitem(ingotID, {
		short_description = ingotName;
		description = tt(ingotName, F('A solid ingot of %s, ready to be worked by a large matter compiler', m.name), 1e3);
		inventory_image = img(lib.image('starsoul-item-ingot.png'));
		wield_image = lib.image 'starsoul-item-ingot.png':colorize(m.color):render();
		groups = {metal = 1, ingot = 1};
		stack_max = 5;
		_starsoul = {
			mass = 1e3;
			material = {
				kind = 'metal';
				metal = id;
			};
			fab = starsoul.type.fab {
				flag = {smelt= true};
				element = comp(1e3);
			};
		};
	});


end)

local function canisterDesc(stack, def)
	def = def or stack:get_definition()._starsoul.canister
	local props = {
		{title = 'Charge Slots', affinity = 'info', desc = tostring(def.slots)};
	};
	if stack then
		local inv = starsoul.item.container(stack)
		for i,e in ipairs(inv:list 'elem') do
			local comp = e:get_definition()._starsoul.fab
			table.insert(props, {
				title = comp:formula();
				desc = lib.math.si('g', e:get_count());
				affinity = 'good';
			})
		end
		-- TODO list masses
	end
	return starsoul.ui.tooltip {
		title = def.name, desc = def.desc or 'A canister that can store a charge of elemental powder, gas, or liquid';
		color = lib.color(0.2,0.1,0.1);
		props = props;
	};	
end

starsoul.item.canister = lib.registry.mk 'starsoul:canister';
starsoul.item.canister.foreach('starsoul:item-gen', {}, function(id, c)
	minetest.register_craftitem(id, {
		short_description = c.name;
		description = canisterDesc(nil, c);
		inventory_image = c.image or 'starsoul-item-element-canister.png';
		groups = {canister = 1};
		stack_max = 1;
		_starsoul = {
			canister = c;
			container = {
				handle = function(stack, oldstack)
					stack:get_meta():set_string('description', canisterDesc(stack))
					return stack
				end;
				list = {
					elem = {
						key = 'starsoul:canister_elem';
						accept = 'powder';
						sz = c.slots;
					};
				};
			};
		};
	})
end)
