--- gemstones
local shards_per_gem = 9

local register_gem = function(name,gem)
	local itemname = gem.foreign or 'sorcery:gem_' .. name
	local shardname = gem.foreign_shard or 'sorcery:gem_' .. name .. '_shard'
	local amuletname = gem.foreign_amulet or 'sorcery:gem_' .. name .. '_amulet'
	local polishedname = gem.foreign_polished or 'sorcery:gem_' .. name .. '_polished'

	sorcery.data.gems[name].parts = {
		item = itemname;
		shard = shardname;
		amulet = amuletname;
	}

	local tools, armors = sorcery.matreg.tools, sorcery.matreg.armors
	if gem.tools then for t,c in pairs(tools) do
		sorcery.matreg.lookup[(gem.items and gem.items[t]) or ('sorcery:' .. t .. '_' .. name)] = {
			gem = true;
			id = name; data = gem;
			value = c.cost*shards_per_gem;
		}
	end end
	if gem.armor then for a,c in pairs(armors) do
		sorcery.matreg.lookup[(gem.items and gem.items[a]) or ('sorcery:' .. a .. '_' .. name)] = {
			gem = true;
			id = name, data = gem;
			value = c.cost*shards_per_gem;
		}
	end end

	if gem.foreign_shard then
		minetest.clear_craft {output=shardname}
	else
		minetest.register_craftitem(shardname, {
			description = sorcery.lib.str.capitalize(name) .. ' shard';
			inventory_image = 'sorcery_gem_' .. name .. '_shard.png';
			groups = { gemshard = 1; crystalshard = 1; sorcery_shard = 1; };
			_sorcery = {
				material = {
					gem = true;
					id = name, data = gem;
					raw = true, value = 1;
				};
				recipe = {
					canonical = {
						craft = {
							{'','xdecor:hammer',''};
							{'',itemname,''};
						};
					}
				};
			};
		})
	end
	gem.durability = gem.durability or (gem.hardness or 1) * 100
	if not gem.foreign_amulet then
		local img = sorcery.lib.image
		local colorized_stone = function(file)
			return img(file):multiply(sorcery.lib.color(gem.tone):brighten(1.1))
		end
		local img_stone = colorized_stone('sorcery_amulet.png')
		local img_stone_tiny = colorized_stone('sorcery_amulet_embedded.png')
		local img_sparkle = img('sorcery_amulet_sparkle.png')
		local img_necklace = img('sorcery_amulet_necklace.png')
		local useamulet = function(stack,user,target)
			local sp = sorcery.amulet.getspell(stack)
			if not sp or not sp.cast then return nil end

			local usedamulet if stack:get_count() == 1 then
				usedamulet = stack
			else
				usedamulet = ItemStack(stack)
				usedamulet:set_count(1)
			end
			local probe = sorcery.spell.probe(user:get_pos())
			-- amulets don't work in antimagic fields, though some may want to 
			-- implement this logic themselves (for instance to check a range)
			if (probe.disjunction and not sp.ignore_disjunction) then return nil end
			local stats = sorcery.amulet.stats(usedamulet)

			local ctx = {
				caster = user;
				target = target;
				stats = stats;
				wield = usedamulet;
				amulet = stack:get_definition()._sorcery.amulet;
				meta = stack:get_meta(); -- avoid spell boilerplate
				color = sorcery.lib.color(sp.tone);
				today = minetest.get_day_count();
				probe = probe;
				heading = {
					pos   = user:get_pos();
					yaw   = user:get_look_dir();
					pitch = user:get_look_vertical();
					angle = user:get_look_horizontal();
					eyeheight = user:get_properties().eye_height;
				};

				sound = sp.sound or "xdecor_enchanting"; --FIXME make own sounds
				sparkle = true;
			}
			local res = sp.cast(ctx)

			if res == nil or res == true and ctx.sound then
				minetest.sound_play(ctx.sound, { 
					pos = user:get_pos();
					gain = 1;
				})
			end
			if ctx.sparkle then
				sorcery.vfx.cast_sparkle(user, ctx.color, stats.power,0.2)
			end
			local infinirune = minetest.check_player_privs(user, 'sorcery:infinirune')
			if res == nil then
				if not infinirune then sorcery.amulet.setrune(usedamulet) end
			end

			if stack:get_count() == 1 then
				return ctx.wield
			else
				if not infinirune then
					stack:take_item(1)
					local leftover = user:get_inventory():add_item('main',usedamulet)
					if leftover and leftover:get_count() > 0 then
						minetest.add_item(user:get_pos(), leftover)
					end
				end
				return stack
			end
		end;

		local stonematprops = {
			gem = true, id = name, data = gem;
			value = (5 * shards_per_gem) + 4;
		};
		minetest.register_craftitem(amuletname, {
			description = sorcery.lib.str.capitalize(name) .. ' amulet';
			inventory_image = img_sparkle:blit(img_stone):blit(img_necklace):render();
			wield_image = img_sparkle:blit(img_stone):render();
			wield_scale = { x = 0.6, y = 0.6, z = 0.6 };
			groups = { sorcery_amulet = 1 };
			on_use = useamulet;
			_sorcery = { material = stonematprops, amulet = { base=name }};
		})
		minetest.register_craftitem(polishedname, {
			description = 'Polished ' .. name;
			inventory_image = img_sparkle:blit(img_stone):render();
			wield_scale = { x = 0.6, y = 0.6, z = 0.6 };
			_sorcery = { material = stonematprops };
		})
		minetest.register_craft {
			output = amuletname;
			type = 'shapeless';
			recipe = {
				polishedname;
				'basic_materials:silver_wire';
			};
			replacements = {
				{'basic_materials:silver_wire', 'basic_materials:empty_spool'};
			};
		}
		sorcery.lathe.register {
			input = itemname;
			output = polishedname;
			tech = 'intaglio';
			cost = 1;
		}
		sorcery.register.metals.foreach('sorcery:mk-amulet-frames-'..name,{'sorcery:generate'}, function(metalid,metal)
			if not metal.amulet then return end
			local framedid = string.format("%s_frame_%s", amuletname, metalid)
			local img_frame = img(string.format('sorcery_amulet_frame_%s.png',metalid))
			minetest.register_craftitem(framedid, {
				description = string.format("%s-framed %s amulet",sorcery.lib.str.capitalize(metalid), name);
				inventory_image = img_stone_tiny:blit(img_frame):blit(img_necklace):render();
				wield_image = img_stone_tiny:blit(img_frame):render();
				wield_scale = { x = 0.6, y = 0.6, z = 0.6 };
				groups = { sorcery_amulet = 1 };
				on_use = useamulet;
				_sorcery = {
					amulet = { base = name, frame = metalid };
				};
			})
			--local frag = metal.parts.fragment
			local disc = metal.parts.disc
			minetest.register_craft {
				output = framedid;
				recipe = {
					{amuletname};
					{disc};
					-- {'',  frag,''};
					-- {frag,amuletname,frag};
					-- {'',  frag,''};
				};
			}
			minetest.register_craft {
				output = amuletname;
				type = 'shapeless';
				recipe = { framedid, 'xdecor:hammer'; };
				replacements = {
					{'xdecor:hammer', 'xdecor:hammer'};
					{framedid, disc};
				};
			}
		end)
	end
	minetest.register_craft {
		type = 'shapeless';
		recipe = (minetest.get_modpath('xdecor') and {
			'xdecor:hammer', itemname;
		}) or { itemname };
		output = shardname .. ' 9';
		replacements = {
			{'xdecor:hammer','xdecor:hammer'};
		};
	}
	minetest.register_craft {
		type = 'shapeless';
		recipe = {
			shardname, shardname, shardname;
			shardname, shardname, shardname;
			shardname, shardname, shardname;
		};
		output = itemname;
	};
-- 	minetest.register_craft {
-- 		recipe = {
-- 			{shardname,itemname,shardname};
-- 			{itemname,itemname,itemname};
-- 			{shardname,itemname,shardname};
-- 		};
-- 		output = amuletname;
-- 	};

	-- generate lenses and crafting recipes
	for _, kind in pairs { 'amplifier','rectifier','concave','convex' } do
		local id = 'sorcery:lens_' .. kind .. '_' .. name
		minetest.register_tool(id, {
			inventory_image = sorcery.lib.image('sorcery_lens_overlay_gold.png'):
				blit(sorcery.lib.image('sorcery_lens_' .. kind .. '.png'):
					multiply(sorcery.lib.color(gem.tone):brighten(1.1))):
				render();
			description = sorcery.lib.str.capitalize(name) .. ' ' .. sorcery.lib.str.capitalize(kind) .. ' Lens';
			groups = { sorcery_enchanting_lens = 1 };
			_proto = {
				gem = name;
				kind = kind;
			};
		})
	end
	do local casing = 'sorcery:fragment_gold'
		minetest.register_craft {
			output = 'sorcery:lens_convex_' .. name;
			recipe = {
				{'',       casing, ''};
				{itemname, casing, itemname};
				{'',       casing, ''};
			};
		}
		minetest.register_craft {
			output = 'sorcery:lens_concave_' .. name;
			recipe = {
				{itemname, casing, itemname};
				{'',       casing, ''};
				{itemname, casing, itemname};
			};
		}
		minetest.register_craft {
			output = 'sorcery:lens_amplifier_' .. name;
			recipe = {
				{itemname, casing, itemname};
				{shardname,casing, shardname};
				{shardname,casing, shardname};
			};
		}
		minetest.register_craft {
			output = 'sorcery:lens_rectifier_' .. name;
			recipe = {
				{shardname,casing, shardname};
				{'basic_materials:silver_wire',casing,'basic_materials:silver_wire'};
				{itemname, casing, itemname};
			};
			replacements = {
				{'basic_materials:silver_wire', 'basic_materials:empty_spool'};
				{'basic_materials:silver_wire', 'basic_materials:empty_spool'};
			};
		}
	end

	if gem.foreign then return false end
	minetest.register_craftitem(itemname, {
		description = sorcery.lib.str.capitalize(name);
		inventory_image = 'sorcery_gem_' .. name .. '.png';
		groups = { gem = 1; crystal = 1; sorcery_gem = 1; };
		_sorcery = {
			material = {
				id = name, data = gem;
				raw = true, value = shards_per_gem;
			};
		};
	})
	local tools = gem.tools
	if tools == nil then tools = {
		'group:pickaxe';
		'group:pick'; -- FUCK YOU INSTANT_ORES
		'~default:enchanted_pick_'; -- FUCK YOU XDECOR
	} end

	local ores = gem.ores
	if ores == nil then ores = {
		['default:stone_with_coal'] = 1.0;
		['default:stone_with_iron'] = 0.7;
		['default:stone_with_copper'] = 0.6;
		['default:stone_with_tin'] = 0.8;
		['default:stone_with_gold'] = 1.5;
		--
		['sorcery:stone_with_cobalt'] = 0.9;
		['sorcery:stone_with_tungsten'] = 0.3;
		['sorcery:stone_with_platinum'] = 0.6;
		['sorcery:stone_with_iridium'] = 1.6;
		['sorcery:stone_with_lithium'] = 1.4;
	} end

	for ore,fac in pairs(ores) do
		local drops = minetest.registered_nodes[ore].drop
		local newdrops
		if type(drops) == 'string' then
			newdrops = {
				max_items = 1;
				items = {
					{ rarity = 1; items = { drops }; };
				};
			}
		else newdrops = sorcery.lib.tbl.copy(drops) end
		
		newdrops.max_items = newdrops.max_items + 1
		newdrops.items[#newdrops.items + 1] = {
			rarity = gem.rarity * fac;
			items = { itemname };
		};

		minetest.override_item(ore, {drop = newdrops})
		-- might be possible to just edit it in place, since we're
		-- referring to registered_nodes anyway, but i don't want
		-- to chance it; god knows what's going on under the hood
	end
end

-- for g,v in pairs(sorcery.data.gems) do sorcery.register_gem(g,v) end
sorcery.register.gems.foreach('sorcery:generate',{},register_gem)

sorcery.gem = {
	getdrops = function(fac)
		items = {}
		for g,v in pairs(sorcery.data.gems) do
			items[#items + 1] = {
				rarity = gem.rarity * fac;
				items = { itemname };
			};
		end
		return items
	end;
};
-- register gem cutting tools
--   - abrasive powder
--   - hand-drill

-- register gem cuts (cube, sphere, circlet, triangle, rod)
-- cube, sphere, and triangle are used in enchanting. all are used in crafting.
