local S = minetest.get_translator("hades_groundplants")

hades_groundplants = {}

local nodenames_to_basenames = {}

--[[ GROUNDPLANT REGISTRATION

Registers a plant that grows on the ground (dirt, sand, gravel, etc.).
This registers a node, or a set of nodes.

Supports multiple growth stages and node coloring (season-based or not).
Only supports plants that occupy a single node. Larger plants, like
plants that occupy 2 nodes at once, are not supported.
For very simple plants that really only need 1 node, e.g. don’t have
seasonal, growth-based or other variations, you probably don’t need
this; just register the node directly instead.

This function is supposed as the lowest common denominator so that
all ground-based plants (farming, bushes, grasses, flowers, etc.) share
a common codebase. To keep thing simple, it ONLY registers the nodes
but not anything else; so any actual growth still needs to be coded
on top.

The node names follow the syntax "<modname>:<basename>_<stage>", where
<stage> is the growth stage (starting at 1).

Groundplants can have multiple growth stages, defined in def.stages.
Using a single growth stage is possible, but not recommended.

The nodes will have the following groups added automatically:
* plant=1: For every node
* plant_stage=s: For every node, s is its plant stage
* not_in_creative_inventory=1: By default, for every node after stage 1
	(can be overridden with `in_creative_inventory` in stages list, see below)

Arguments:

* modname: Name of the mod for which you register the nodes
* basename: Freely-choosable name; see the node name syntax above
* def: Definition table that defines everything:

def: {
	* description: Description of the base node
	* colorable: If true, node uses colors (default: false)
	* set_color_on_place: If true and node is colorable, season-based color is set when placing node (default: false)
	* place_node_override: (optional) Function that returns an alternative basename of the node to place, instead
		of the standard one. If it returns nil, the basename is not changed.
		Takes `itemstack` as its only argument. Can only used if set_color_on_place is true.
	* color_stereotype: A colorstring that defines the 'sterotypical' color that represents the plant overall.
		Used for wield and inventory image. Recommended for plants with seasonal colors: Summer color
	* image: Inventory and wield image (the mod will make some adjustments so that coloring works)
	* palette: Color palette, needed if node is colorable (same as of normal node definition)
	* sounds: Node sounds (same as in normal node def)
	* groups: Node groups (same as in normal node def; actual groups can be modified, see above)
	* buildable_to: same as in normal node def (default: true)
	* stage_groups: List of group names to assign to each node where the group rating is equal to the stage
		E.g. `{"grass_clump"}` assigns group `grass_clump=<stage>` to each node
	* stages: list of stage-based node information, starting with 1, the youngest stage.
		Each entry represents a stage, indexed by its stage number and the following
		node definition fields for each stage:
		* tiles
		* overlay_tiles
		* selection_box
		* collision_box
		* drop
		* description: description override for this stage
		* _tt_help: Help text for this stage (`_tt_help` field for the [tt] mod)
		* image: inventory_image and wield_image
		* extra_groups: list of groups to add to the normal groups, in form `{ [group_name] = group_rating, ... }`
		* in_creative_inventory: set to true to force-allow this stage in creative inventory, set to false to force-forbid it.
}
]]
hades_groundplants.register_groundplant = function(modname, basename, def)

	local inv_image, inv_overlay, paramtype2, on_place
	if def.colorable then
		paramtype2 = "color"
		if def.set_color_on_place then
			on_place = function(itemstack, placer, pointed_thing)
				local old_itemstack = ItemStack(itemstack)
				-- Pick the correct seasonal plant color
				if def.place_node_override then
					local altname = def.place_node_override(itemstack)
					if altname then
						local stage = hades_groundplants.get_stage(itemstack:get_name())
						altname = hades_groundplants.get_new_stage(altname.."_1", stage)
						itemstack:set_name(altname)
					end
				end
				local name = itemstack:get_name()
				local param2 = hades_seasons.get_seasonal_palette_color_param2()
				local ret = minetest.item_place(itemstack, placer, pointed_thing, param2)
				old_itemstack:set_count(ret:get_count())
				return old_itemstack
			end
		end
	else
		inv_image = def.image
	end


	if not def.colorable and def.meshoptions then
		paramtype2 = "meshoptions"
	end

	for s=1, #def.stages do
		local nodename = modname..":"..basename.."_"..s
		nodenames_to_basenames[nodename] = modname..":"..basename

		local groups = table.copy(def.groups)
		if def.stages[s].extra_groups then
			for group, rating in pairs(def.stages[s].extra_groups) do
				groups[group] = rating
			end
		end
		local description
		if def.stages[s].in_creative_inventory == false then
			groups.not_in_creative_inventory = 1
		elseif s > 1 and def.stages[s].in_creative_inventory ~= true then
			groups.not_in_creative_inventory = 1
		end
		if def.stages[s].description then
			description = def.stages[s].description
		elseif s > 1 then
			--~ Description for ground plant on higher growth stages. @1 = plant name, @2 = growth stage, expressed as a number
			description = S("@1 (Stage @2)", def.description, s)
		else
			description = def.description
		end
		local magic_next, grows_to, grows_from
		if #def.stages > 1 then
			if s < #def.stages then
				grows_to = modname..":"..basename.."_"..(s+1)
				magic_next = grows_to
			else
				magic_next = modname..":"..basename.."_1"
			end
			if s > 1 then
				grows_from = modname..":"..basename.."_"..(s-1)
			end
		end
		groups.plant = 1
		groups.plant_stage = s
		if def.stage_groups then
			for g=1, #def.stage_groups do
				groups[def.stage_groups[g]] = s
			end
		end
		if def.colorable then
			-- The inventory_overlay and wield_overlay with the multiply for the nodes
			-- is a workaround for Luanti bug #12578, so that the grass color is
			-- still correct for the wield image.
			-- TODO: Remove the texture overlays once that Luanti bug has been fixed.
			inv_image = def.stages[s].image
			inv_overlay = "("..def.stages[s].image..")".."^[multiply:"..def.color_stereotype
			if def.stages[s].overlay_image then
				inv_overlay = "("..inv_overlay .. ")^"..def.stages[s].overlay_image
			end
		else
			inv_image = def.stages[s].image
			if def.stages[s].overlay_image then
				inv_image = "("..inv_image .. ")^"..def.stages[s].overlay_image
			end
		end
		local buildable_to
		if def.buildable_to ~= nil then
			buildable_to = def.buildable_to
		else
			buildable_to = true
		end
		minetest.register_node(nodename, {
			description = description,
			_tt_help = def.stages[s]._tt_help,
			drawtype = "plantlike",
			tiles = def.stages[s].tiles,
			overlay_tiles = def.stages[s].overlay_tiles,
			use_texture_alpha = "clip",
			place_param2 = def.place_param2,
			inventory_image = inv_image,
			inventory_overlay = inv_overlay,
			wield_image = inv_image,
			wield_overlay = inv_overlay,
			paramtype = "light",
			sunlight_propagates = true,
			paramtype2 = paramtype2,
			palette = def.palette,
			color = def.color_stereotype,
			waving = 1,
			walkable = false,
			is_ground_content = true,
			buildable_to = buildable_to,
			floodable = true,
			drop = def.stages[s].drop,
			groups = groups,
			sounds = def.sounds,
			selection_box = def.stages[s].selection_box,
			collision_box = def.stages[s].collision_box,
			on_place = on_place,

			-- Next and previous growth stages
			_hades_grows_to = grows_to,
			_hades_grows_from = grows_from,

			-- Associate node with certain seasons
			_hades_seasons = def.seasons,
		})
	end
end

-- Given a groundplant node, returns its 'basename',
-- i.e. the name without the stage appendix ("_1", "_2", etc.).
-- Returns nil if the given nodename is not a groundplant.
hades_groundplants.get_basename = function(nodename)
	return nodenames_to_basenames[nodename]
end

-- Given a groundplant node, returns its current stage
-- Returns nil if nodename is not a groundplant.
hades_groundplants.get_stage = function(nodename)
	local base = hades_groundplants.get_basename(nodename)
	if not base then
		return nil
	end
	-- The stage number is always at the end of the nodename
	-- after an underscore
	local splits = string.split(nodename, "_")
	if splits then
		local stage = tonumber(splits[#splits])
		return stage
	end
end

-- Given a groundplant node name and a stage number, returns the
-- full node name of the other node with that stage number.
-- Returns nil if nodename is not a groundplant, or that
-- stage doesn't exist.
hades_groundplants.get_new_stage = function(nodename, stage)
	local base = hades_groundplants.get_basename(nodename)
	if not base then
		return nil
	end
	local new_nodename = base .. "_"..tostring(stage)
	if minetest.registered_nodes[new_nodename] then
		return new_nodename
	else
		return nil
	end
end
