-- hades_refruit
-- Makes fruit regrow on the trees.

local S = minetest.get_translator("hades_refruit")

hades_refruit = {}

--[[ Register a tree fruit for regrowing.
Read readme.txt for info about gameplay mechanics.

The fruit node must already exist. This function
also expects a bunch of other nodes to already exist:
A sapling, a tree trunk and a neighbor node that
"activates" growth.

This function also expects texture files 
for the bud and flower to exist (`bud_texture`
and `flower_texture`, see below).

This will override the fruit node and also registers two new nodes:

* `hades_refruit:bud_<id>: For the bud
* `hades_refruit:flower_<id>: For the flower

The fruit, bud and flower will have the `hades_refruit` group
(1 = bud, 2 = flower, 3 = fruit).

Parameters:

* id: Identifier for node registration and textures (see above)
* def: Definition table with the following arguments:
	* fruit_itemstring: Itemstring for the fruit
	* sapling_itemstring: Itemstring for the sapling of the tree
	* bud_description: Human-facing description of the bud
	* flower_description: Human-facing description of the flower
	* bud_interval: Every X seconds, the bud gets a chance to grow to flower
	* bud_chance: One in X chance the bud grows in each bud_interval
	* flower_interval: Every X seconds, the flower gets a chance to grow to fruit
	* flower_chance: One in X chance the flower grows in each flower_interval
	* fruit_interval: Every X seconds, an off-season fruit has a chance to drop
	* fruit_chance: One in X chance the off-season fruit drops in each fruit_interval
	* bud_texture: Texture for the bud (default: "hades_refruit_bud_<id>.png", not recommended for external mods)
	* flower_texture: Texture for the flower (default: "hades_refruit_flower_<id>.png", not recommended for external mods)
	* neighbors: Bud/flower needs any of the listed nodes to grow
	  to the next stage. Supports groups (same syntax as in minetest.register_abm).
	* trunk: Itemstring of the tree trunk node we need to be close to survive.
	  If there is no such trunk within a taxicab distance of 3, the bud/flower/fruit
	  will die due to leafdecay. 
	* bud_selbox: (optional) Selection box for bud (used in 'selection_box.fixed' node argument)
	* flower_selbox: (optional) Selection box for flower (used in 'selection_box.fixed' node argument)
	* seasons: (optional) List of seasons the fruit will grow in (using identifiers in hades_seasons mod).
	  If nil, grows in any season
	* bud_drop: (optional): Drop table for bud (same as 'drop' in minetest.register_node) (default: drop nothing)
	* flower_drop: (optional): Drop table for flower (same as 'drop' in minetest.register_node) (default: drop nothing)

]]
function hades_refruit.add_hades_refruit(id, def)
	local ndef = minetest.registered_nodes[def.fruit_itemstring]
	local groups = ndef.groups
	if not groups then
		groups = {}
	else
		groups = table.copy(ndef.groups)
	end
	local groups_fruit
	groups_fruit = table.copy(groups)
	groups_fruit.fruit_regrow = 3


	local bud_itemstring = "hades_refruit:bud_"..id
	local flower_itemstring = "hades_refruit:flower_"..id

	minetest.override_item(def.fruit_itemstring, {
		groups = groups_fruit,
		place_param2 = 1,
		after_dig_node = function(pos, oldnode, oldmetadta, digger)
			if oldnode.name == def.fruit_itemstring then
				if oldnode.param2 ~= 0 then
					return
				end
				minetest.set_node(pos, {name = "hades_refruit:bud_"..id})
			else 
				return
			end
		end,
		node_dig_prediction = bud_itemstring,
		_hades_grows_from = def.flower_itemstring,
		_hades_magic_next = bud_itemstring,
		_hades_trees_trunk = def.trunk,
	})

	minetest.override_item(def.sapling_itemstring, {
		_hades_fruit = bud_itemstring,
	})

	local desc_trunk = ItemStack(def.trunk):get_short_description()
	local desc_neighbor = ItemStack(def.neighbors[1]):get_short_description()
	local desc_seasons
	if def.seasons then
		if #def.seasons == hades_seasons.SEASONS then
			desc_seasons = S("All seasons")
		elseif #def.seasons == 1 then
			desc_seasons = S("Season: @1", hades_seasons.SEASON_NAMES[def.seasons[1]])
		else
			local list_seasons = ""
			for s=1, #def.seasons do
				table.insert(list_seasons, hades_seasons.SEASON_NAMES[def.seasons[s]])
			end
			desc_seasons = S("Seasons: @1",
				--~ list separator for list of seasons
				table.concat(list_seasons, S(", ")))
		end
	else
		desc_seasons = S("All seasons")
	end

	local desc_fruit = ItemStack(def.fruit_itemstring):get_short_description()
	local desc_trunk = ItemStack(def.trunk):get_short_description()

	local bud_tt = desc_seasons.."\n"..
		S("Grows to: @1", def.flower_description).."\n"..
		S("Needs @1 to survive", desc_trunk).."\n"..
		S("Needs @1 to grow", desc_neighbor)
	local flower_tt = desc_seasons.."\n"..
		S("Grows to: @1", desc_fruit).."\n"..
		S("Needs @1 to survive", desc_trunk).."\n"..
		S("Needs @1 to grow", desc_neighbor)

	local bud_texture = def.bud_texture or "hades_refruit_bud_"..id..".png"
	local flower_texture = def.flower_texture or "hades_refruit_flower_"..id..".png"

	minetest.register_node(bud_itemstring, {
		description = def.bud_description,
		_tt_help = bud_tt,
		drawtype = ndef.drawtype,
		tiles = {bud_texture},
		inventory_image = bud_texture,
		wield_image = bud_texture,
		paramtype = "light",
		sunlight_propagates = true,
		walkable = false,
		floodable = true,
		selection_box = {
			type = "fixed",
			fixed = def.bud_selbox,
		},
		groups = {fruit_regrow=1, snappy=2,oddly_breakable_by_hand=3,flammable=2,leafdecay=3,leafdecay_drop=1},
		drop = def.bud_drop or {},
		sounds = hades_sounds.node_sound_leaves_defaults(),
		_hades_grows_to = flower_itemstring,
		_hades_magic_next = flower_itemstring,
		_hades_trees_trunk = def.trunk,
	})
	minetest.register_node(flower_itemstring, {
		description = def.flower_description,
		_tt_help = flower_tt,
		drawtype = ndef.drawtype,
		tiles = {flower_texture},
		inventory_image = flower_texture,
		wield_image = flower_texture,
		paramtype = "light",
		sunlight_propagates = true,
		walkable = false,
		floodable = true,
		selection_box = {
			type = "fixed",
			fixed = def.flower_selbox,
		},
		groups = {fruit_regrow=2, snappy=2,oddly_breakable_by_hand=3,flammable=2,leafdecay=3,leafdecay_drop=1},
		drop = def.flower_drop or {},
		sounds = hades_sounds.node_sound_leaves_defaults(),
		_hades_grows_from = bud_itemstring,
		_hades_grows_to = def.fruit_itemstring,
		_hades_magic_next = def.fruit_itemstring,
		_hades_trees_trunk = def.trunk,
	})

	local is_in_season = function()
		if not def.seasons then
			return true
		end
		local season = hades_seasons.get_season()
		if not season then
			return nil
		end
		for s=1, #def.seasons do
			if season == def.seasons[s] then
				return true
			end
		end
		return false
	end

	-- Grow bud to flower
	minetest.register_abm({
		label = "Grow "..bud_itemstring.." to "..flower_itemstring,
		nodenames = {"hades_refruit:bud_"..id},
		neighbors = def.neighbors,
		interval = def.bud_interval,
		chance = def.bud_chance,
		action = function(pos, node)
			if is_in_season() == true then
				minetest.set_node(pos, {name="hades_refruit:flower_"..id})
			end
		end,
	})

	-- Grow flower to fruit, or degrow to bud if out-of-season
	minetest.register_abm({
		label = "Grow or degrow "..flower_itemstring.." to "..def.fruit_itemstring,
		nodenames = {"hades_refruit:flower_"..id},
		neighbors = def.neighbors,
		interval = def.flower_interval,
		chance = def.flower_chance,
		action = function(pos, node)
			local in_season = is_in_season()
			if in_season == true then
				-- grow if in-season
				minetest.set_node(pos, {name=def.fruit_itemstring})
			elseif in_season == false then
				-- degrow if out-of-season
				minetest.set_node(pos, {name=bud_itemstring})
			end
		end,
	})

	-- Drop fruit if out of season
	if def.fruit_interval and def.fruit_chance then
		minetest.register_abm({
			label = "Drop out-of-season "..def.fruit_itemstring,
			nodenames = {def.fruit_itemstring},
			interval = def.fruit_interval,
			chance = def.fruit_chance,
			action = function(pos, node)
				if is_in_season() == false then
					-- degrow to bud and drop fruit as item
					minetest.set_node(pos, {name=bud_itemstring})
					minetest.add_item(pos, def.fruit_itemstring)
				end
			end,
		})
	end

end

-- Register some fruits to regrow
dofile(minetest.get_modpath("hades_refruit").."/register.lua")
