local u = sorcery.lib
sorcery.registry.mk('infusions',false)
sorcery.register.residue.meld(sorcery.data.compat.residue)

sorcery.register_potion_tbl = function(tbl) -- :/
	return sorcery.register_potion(tbl.name,tbl.label,tbl.desc,tbl.color,tbl.imgvariant,tbl.glow,tbl.extra)
end
sorcery.register_potion = function(name,label,desc,color,imgvariant,glow,extra)
	local image = 'sorcery_liquid_'..(imgvariant or 'dull')..'.png' .. 
		'^[multiply:'..tostring(color)..
		'^vessels_glass_bottle.png'

	sorcery.register.residue.link('sorcery:' .. name, 'vessels:glass_bottle')
	local node = {
		description = --color:darken(0.8):bg(
			sorcery.lib.ui.tooltip {
				title = label;
				desc = desc;
				color = color:readable();
			};
			-- label .. (desc and ("\n" .. color:readable():fmt(desc)) or '')
		--);
		short_description = label;
		drawtype = "plantlike";
		tiles = {image};
		inventory_image = image;
		paramtype = "light";
		is_ground_content = false;
		light_source = glow and math.min(minetest.LIGHT_MAX,glow) or 0;
		drop = 'sorcery:' .. name;
		walkable = false;
		selection_box = {
			type = "fixed",
			fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25}
		};
		on_construct = function(pos)
			minetest.get_meta(pos):set_string('infotext',label)
		end;
		sounds = default.node_sound_glass_defaults();
	}
	if extra then for k,v in pairs(extra) do node[k] = v end end
	if not node.groups then node.groups = {} end
	node.groups.dig_immediate = 3;
	node.groups.attached_node = 1;
	node.groups.vessel = 1;
	node.groups.not_in_creative_inventory = 1;
	sorcery.lib.node.reg_autopreserve("sorcery:"..name, node)
end

sorcery.register_oil = function(name,label,desc,color,imgvariant,extra)
	local image = 'xdecor_bowl.png^(sorcery_oil_' .. (imgvariant or 'dull') .. '.png^[colorize:'..tostring(color)..':140)'
	sorcery.register.residue.link('sorcery:' .. name, 'xdecor:bowl')
	extra.description = label;
	extra.inventory_image = image;
	if not extra.groups then extra.groups = {} end
	extra.groups.sorcery_oil = 1
	minetest.register_craftitem('sorcery:' .. name, extra)
end

sorcery.register_potion('blood', 'Blood', 'A bottle of sacrificial blood, imbued with stolen (or perhaps donated) life force', u.color(219,19,14), nil, nil, {
	_sorcery = {
		life_store = 4;
		container = {
			type = 'vessel';
			hold = 'liquid';
			has = 'sorcery:blood';
			empty = 'vessels:glass_bottle';
			charge = 3;
		};
	};
})
sorcery.register_potion('potion_water', 'Water Bottle', 'A bottle of plain water', u.color(43,90,162),nil,nil,{
	_sorcery = {
		container = {
			type = 'vessel';
			hold = 'liquid';
			has = 'default:water';
			empty = 'vessels:glass_bottle';
			charge = 3;
		};
	};
})
sorcery.register_potion('holy_water', 'Holy Water','A bottle of consecrated water',u.color(94,138,206),'sparkle',6,{
	_sorcery = {
		container = {
			type = 'vessel';
			hold = 'liquid';
			has = 'sorcery:water_holy';
			empty = 'vessels:glass_bottle';
			charge = 3;
		};
	};
})

local create_infusion_recipe = function(id,potion,default_basis,proto)
	if potion.infusion then
		sorcery.register.infusions.link {
			infuse = potion.infusion;
			into = potion.basis or default_basis;
			output = 'sorcery:' .. id;
			_proto = proto;
		}
	end
end

-- for n,v in pairs(sorcery.data.potions) do
local kind_potion = {
	label = 'Potion';
	kind = 'A mystical liquid crucial to the art of alchemy';
}
sorcery.register.potions.foreach('sorcery:mknodes',{},function(n,v)
	local color = u.color(v.color)
	local kind = v.style
	local glow = v.glow
	local id = 'potion_' .. string.lower(n)
	local desc = 'A ' .. ((glow and 'glowing ') or '') ..
		'bottle of ' .. string.lower(n) .. 
		((kind == 'sparkle' and ', fiercely bubbling') or '') ..
		' liquid'
	local fullname = n .. ' Potion'
	sorcery.liquid.register{
		id = 'sorcery:'..id;
		name = fullname;
		color = v.color;
		proto = v;
		kind = 'sorcery:potion';
		measure = sorcery.liquid.units.draught;
		containers = {
			['vessels:glass_bottle'] = 'sorcery:' .. id;
		};
	}
	v.kind = kind_potion;
	sorcery.register_potion(id, fullname, desc, color, kind, glow, {
		groups = {
			sorcery_potion = 1;
			sorcery_magical = 1;
		};
		_proto = v;
		_sorcery = {
			container = {
				type = 'vessel';
				hold = 'liquid';
				has = 'sorcery:' .. id;
				empty = 'vessels:glass_bottle';
				charge = 3;
			};
		};
	})
	create_infusion_recipe(id,v,'sorcery:potion_serene',{data=v,name=fullname})
end)

-- for n,potion in pairs(sorcery.data.draughts) do
local kind_draught = {
	label = 'Draught';
	desc = 'A drink that will suffuse your body and spirit with mystic energies';
}
sorcery.register.draughts.foreach('sorcery:mknodes',{},function(n,potion)
	local name = 'draught_' .. n
	potion.kind = kind_draught
	local behavior = {
		_proto = potion;
		groups = {
			sorcery_potion = 2;
			sorcery_draught = 1;
			sorcery_magical = 1;
			sorcery_usable_magic = 1;
		};
		on_use = function(stack, user, pointat)
			local pproto = stack:get_definition()._proto
			if potion.effect(stack, user, pproto) == false then return nil end
			local meta = stack:get_meta()
			local force = meta:get_int('force');
			local duration = pproto:duration(meta);
			minetest.add_particlespawner {
				amount = (7 + (10 * force)) * duration;
				time = duration;
				minpos = { x = -0.1; y = 0; z = -0.1; };
				maxpos = { x = 0.1; y = 2; z = 0.1; };
				minvel = { x = -0.1; y = 0; z = -0.1; };
				maxvel = { x = 0.1; y = 0; z = 0.1; };
				minacc = { x = 0; y = 0.1; z = 0; };
				maxacc = { x = 0; y = 1; z = 0; };
				minexptime = 1;
				maxexptime = 4;
				maxsize = 2 + force;
				attached = user;
				texture = u.image('sorcery_sparkle.png'):multiply(u.color(potion.color)):render();
				glow = 14;
			}
			stack:take_item(1)
			minetest.sound_play('sorcery_drink', {
				pos = user:get_pos();
				max_hear_distance = 12;
			}, true)
			local ret = ItemStack("vessels:glass_bottle")
			if stack:is_empty() then stack = ret else
				if user:get_inventory():room_for_item('main',ret) then
					user:get_inventory():add_item('main',ret)
				else
					minetest.add_item(user.get_pos(), ret)
				end
			end
			return stack
		end
	}
	local fullname = potion.name .. ' Draught'
	sorcery.register_potion(name, fullname,
		potion.desc,
		u.color(potion.color),
		potion.style or 'dull',
		potion.glow or 0,
		behavior)
	create_infusion_recipe(name,potion,'sorcery:potion_luminous',{data=potion,name=fullname})
end)

-- for n,elixir in pairs(sorcery.data.elixirs) do
local kind_elixir = {
	label = 'Elixir';
	desc = 'A special kind of potion that enhances the particular qualities of other alchemical brews';
}
sorcery.register.elixirs.foreach('sorcery:mknodes',{},function(n,elixir)
	local color = u.color(elixir.color)
	local id = 'elixir_' .. string.lower(n)
	local fullname = 'Elixir of ' .. n
	elixir.kind = kind_elixir;
	sorcery.register_potion(id, fullname, nil, color, 'dull', false, {
		_proto = elixir;
		groups = {
			sorcery_elixir = 1;
			sorcery_magical = 1;
		};
	})
	create_infusion_recipe(id,elixir,'sorcery:potion_misty',{data=elixir,name=fullname})
end)

-- for n,v in pairs(sorcery.data.oils) do
sorcery.register.oils.foreach('sorcery:mknodes',{},function(n,v)
	local color = u.color(v.color)
	local kind = v.style
	local id = 'oil_' .. n
	n = v.name or u.str.capitalize(n)
	sorcery.register_oil(id, n .. ' Oil', nil, color, kind, {
		groups = { sorcery_oil = 1 };
	})
end)

-- for n,v in pairs(sorcery.data.greases) do
sorcery.register.greases.foreach('sorcery:mknodes',{},function(n,v)
	local color = u.color(v.color)
	local kind = v.style
	sorcery.register_oil('grease_' .. n, u.str.capitalize(n) .. ' Grease', nil, color, kind, {
		groups = { sorcery_grease = 1 }
	})
end)

-- for n,v in pairs(sorcery.data.philters) do
local kind_philter = {
	label = 'Philter';
	desc = 'A special kind of potion that wooden rods can be soaked in to imbue them with special powers and transform them into wands';
}
sorcery.register.philters.foreach('sorcery:mknodes',{},function(n,v)
	local color = u.color(v.color)
	local id = 'philter_' .. n
	local name = v.name or u.str.capitalize(n)
	if not v.name then v.name = name end
	local fullname = name .. ' Philter'
	v.kind = kind_philter
	sorcery.register_potion(id, fullname, v.desc, color, 'sparkle',v.glow or 4, {
		_proto = v;
		_protoname = n;
		groups = {
			sorcery_magical = 1;
			sorcery_philter = 1;
		};
	})
	v.quals = {force = true};
	create_infusion_recipe(id,v,'sorcery:potion_viscous',{data=v,name=fullname})
end)

-- for n,v in pairs(sorcery.data.extracts) do
sorcery.register.extracts.foreach('sorcery:mknodes',{},function(n,v)
	local item = v[1]
	local color = u.color(v[2])
	local name = 'extract_' .. n
	local liqid = 'sorcery:' .. name
	local desc = u.str.capitalize(n) .. ' Extract'
	sorcery.register_potion(name, desc, nil, color, 'sparkle', false, {
		groups = {
			sorcery_extract = 1;
			sorcery_container = 2;
		};
		_sorcery = {
			extract = {
				of = item;
				proto = v;
			};
			container = {
				type = 'vessel';
				hold = 'liquid';
				charge = 3;
				has = liqid;
				empty = 'vessels:glass_bottle';
			};
		};
	})

	sorcery.liquid.register {
		id = liqid;
		name = desc;
		kind = 'sorcery:extract';
		proto = v;
		color = v[2];
		measure = sorcery.liquid.units.pint;
		containers = {
			['vessels:glass_bottle'] = liqid;
		};
	}

	local add_alcohol = function(booze)
		minetest.register_craft {
			type = "shapeless";
			recipe = {
				booze;
				item, item, item;
				item, item, item;
				"farming:mortar_pestle";
			};
			output = 'sorcery:' .. name;
			replacements = {
				{"farming:mortar_pestle", "farming:mortar_pestle"};
			};
		}
	end
	-- need a relatively pure alcohol for this, tho other alcohols can be used
	-- for potionmaking in other ways
	add_alcohol('farming:bottle_ethanol')
	if minetest.get_modpath('wine') then
		add_alcohol('wine:glass_vodka')
	end
end)
