local S = minetest.get_translator("hades_grass")

hades_grass = {}

-- "stereotypical" colors for grass for the inventory and wield image
local GRASS_COLOR_STEREOTYPE = "#AEFF5F"
local DEAD_GRASS_COLOR_STEREOTYPE = "#FFE770"
local TROPICAL_GRASS_COLOR_STEREOTYPE = "#598E28"

local grass_drop = {
	max_items = 1,
	items = {
		{ items = { "hades_grass:seed_grass 2" }, rarity = 13 },
		{ items = { "hades_grass:grass_1" } },
	}
}

-- Grass grows or withers depending on the block it was placed on
local RATE_GOOD = 2 -- grass grows up to seasonal limit
local RATE_MED = 1 -- grass size limited to 1
local RATE_BAD = 0 -- grass withers and dies
local grass_surfaces = {
	["hades_core:clay"] = RATE_GOOD,
	["hades_core:fertile_sand"] = RATE_GOOD,
	["hades_furniture:plant_pot"] = RATE_MED,
	["hades_core:volcanic_sand"] = RATE_MED,
	["hades_core:gravel"] = RATE_MED,
	["hades_core:tuff"] = RATE_MED,
	["hades_core:tuff_baked"] = RATE_MED,
	["hades_core:mossytuff"] = RATE_MED,
}

-- Returns rating of surface level for grass
local get_grass_surface_level = function(nodename)
	if grass_surfaces[nodename] then
		return grass_surfaces[nodename]
	elseif minetest.get_item_group(nodename, "dirt") ~= 0 then
		return RATE_GOOD
	elseif minetest.get_item_group(nodename, "soil") > 1 then
		return RATE_GOOD
	elseif minetest.get_item_group(nodename, "soil") == 1 then
		return RATE_MED
	end
	return RATE_BAD
end

local grass_stages = {}
local dead_grass_stages = {}
for s=1, 5 do
	table.insert(grass_stages,
		{
			tiles = {"hades_grass_plant_colorable_"..s..".png"},
			image = "hades_grass_plant_colorable_"..s..".png",
			drop = grass_drop,
			selection_box = {
				type = "fixed",
				fixed = {-6/16, -0.5, -6/16, 6/16, -3/16, 6/16},
			},
		})
	table.insert(dead_grass_stages,
		{
			tiles = {"hades_dead_grass_plant_colorable_"..s..".png"},
			image = "hades_dead_grass_plant_colorable_"..s..".png",
			drop = "hades_grass:dead_grass_1",
			selection_box = {
				type = "fixed",
				fixed = {-6/16, -0.5, -6/16, 6/16, -3/16, 6/16},
			},
		})

end

hades_groundplants.register_groundplant("hades_grass", "grass", {
	description = S("Grass Clump"),
	stages = grass_stages,
	--[[ The grass color palette represents the seasonal grass color
	for each season, plus "transitional" colors for when the
	grass changes color from one season to another.
		* 0: spring
		* 1: spring to summer
		* 2: summer
		* 3: summer to fall
		* 4: fall
		* 5: fall to spring

	The concept of the grass palette is the reference palette for all
	seasonal foliage colors (leaves, bushes, etc.); the meaning of
	palette indexes for other foliage nodes should be the same or
	similar.
	]]
	palette = "hades_core_palette_grass.png",
	colorable = true,
	set_color_on_place = true,
	color_stereotype = GRASS_COLOR_STEREOTYPE,
	groups = {snappy=3,flammable=3,grass=1,grass_spread=1,attached_node=1},
	stage_groups = {"grass_clump"},
	sounds = hades_sounds.node_sound_grass_defaults(),
})

hades_groundplants.register_groundplant("hades_grass", "dead_grass", {
	description = S("Dead Grass Clump"),
	stages = dead_grass_stages,
	palette = "hades_core_palette_dead_grass.png",
	colorable = true,
	color_stereotype = DEAD_GRASS_COLOR_STEREOTYPE,
	groups = {snappy=3,flammable=3,grass=1,attached_node=1},
	stage_groups = {"dead_grass_clump"},
	sounds = hades_sounds.node_sound_grass_defaults(),
})


hades_seeds.register_seed("hades_grass:seed_grass", {
	description = S("Grass Seed"),
	image = "hades_grass_grass_seed.png",
	surface_check = function(node)
		-- Allow planting on good and med surface
		local rate = get_grass_surface_level(node.name)
		return rate == RATE_GOOD or rate == RATE_MED
	end,
	_tt_help = S("Grows on Dirt, Soil, Clay, Fertile Sand in light").."\n"..S("All seasons"),
	_hades_grows_to = "hades_grass:grass_1",
})

minetest.register_abm({
	label = "Grow grass seeds in light",
	nodenames = {"hades_grass:seed_grass"},
	interval = 10,
	chance = 25,
	action = function(pos, node)
		local light = minetest.get_node_light(pos)
		if light < 8 then
			return
		end
		local param2 = hades_seasons.get_seasonal_palette_color_param2()
		local below = {x=pos.x, y=pos.y-1, z=pos.z}
		local bnode = minetest.get_node(below)
		-- Growth behavior depends on node below ...
		if bnode.name == "hades_core:dirt" then
			-- increase dirt grass level by 1
			local next_node = hades_core.get_next_grass_cover_level(bnode.name)
			minetest.remove_node(pos)
			minetest.set_node(below, {name = next_node, param2 = param2})
			return
		elseif bnode.name == "hades_core:dirt_with_grass" or bnode.name == "hades_furniture:plant_pot" then
			-- grow grass clump on (full) dirt with grass
			minetest.set_node(pos, {name = "hades_grass:grass_1", param2 = param2})
			return
		elseif get_grass_surface_level(bnode.name) == RATE_GOOD then
			-- if on partial dirt-with-grass, do nothing (wait until it's fully grass-covered)
			if minetest.get_item_group(bnode.name, "dirt") ~= 0 then
				return
			else
				-- grow grass clump on any other 'good' surface
				minetest.set_node(pos, {name = "hades_grass:grass_1", param2 = param2})
				return
			end
		end
		-- Seeds are on wrong node, let's kill them!
		minetest.remove_node(pos)
	end
})

for s=1, 5 do
	table.insert(grass_stages,
		{
			tiles = {"hades_grass_plant_colorable_"..s..".png"},
			image = "hades_grass_plant_colorable_"..s..".png",
			drop = grass_drop,
			selection_box = {
				type = "fixed",
				fixed = {-6/16, -0.5, -6/16, 6/16, -3/16, 6/16},
			},
		})
	table.insert(dead_grass_stages,
		{
			tiles = {"hades_dead_grass_plant_colorable_"..s..".png"},
			image = "hades_dead_grass_plant_colorable_"..s..".png",
			drop = "hades_grass:dead_grass_1",
			selection_box = {
				type = "fixed",
				fixed = {-6/16, -0.5, -6/16, 6/16, -3/16, 6/16},
			},
		})

end

hades_groundplants.register_groundplant("hades_grass", "junglegrass", {
	description = S("Tropical Grass"),
	stages = {
		{
			description = S("Young Tropical Grass"),
			tiles = {"hades_grass_tropical_young_colorable.png"},
			image = "hades_grass_tropical_young_colorable.png",
			drop = { max_items = 1,
				items = {
					{ items = { "hades_grass:junglegrass_1" } },
				}
			},
			selection_box = {
				type = "fixed",
				fixed = {-4/16, -0.5, -4/16, 4/16, 4/16, 4/16},
			},
			in_creative_inventory = true,
		},
		{
			description = S("Tropical Grass"),
			tiles = {"hades_grass_tropical_colorable.png"},
			image = "hades_grass_tropical_colorable.png",
			drop = { max_items = 1,
				items = {
					{ items = { "hades_grass:seed_junglegrass 2" }, rarity = 13 },
					{ items = { "hades_grass:junglegrass_2" } },
				}
			},
			selection_box = {
				type = "fixed",
				fixed = {-6/16, -0.5, -6/16, 6/16, 0.5, 6/16},
			},
			in_creative_inventory = true,
		}
	},
	palette = "hades_core_palette_tropical_grass.png",
	colorable = true,
	set_color_on_place = true,
	color_stereotype = TROPICAL_GRASS_COLOR_STEREOTYPE,
	groups = {snappy=3,flammable=3,grass=1,grass_spread=1,attached_node=1},
	stage_groups = {"junglegrass"},
	sounds = hades_sounds.node_sound_grass_defaults(),
})

hades_seeds.register_seed("hades_grass:seed_junglegrass", {
	description = S("Tropical Grass Seed"),
	image = "hades_grass_tropical_grass_seed.png",
	surface_check = function(node)
		-- Allow planting on good or med surface
		local rate = get_grass_surface_level(node.name)
		return rate == RATE_GOOD or rate == RATE_MED
	end,
	_tt_help = S("Grows on Dirt, Soil, Clay, Fertile Sand in light").."\n"..S("All seasons"),
	_hades_grows_to = "hades_grass:junglegrass_1",
})

minetest.register_abm({
	label = "Grow tropical grass seeds in light",
	nodenames = {"hades_grass:seed_junglegrass"},
	interval = 11,
	chance = 26,
	action = function(pos, node)
		local light = minetest.get_node_light(pos)
		if light < 8 then
			return
		end
		local below = {x=pos.x, y=pos.y-1, z=pos.z}
		local bnode = minetest.get_node(below)
		local rating = get_grass_surface_level(bnode.name)
		if rating == RATE_GOOD or rating == RATE_MED then
			-- grow tropical grass on good or medium surface
			local param2 = hades_seasons.get_seasonal_palette_color_param2()
			minetest.set_node(pos, {name = "hades_grass:junglegrass_1", param2 = node.param2})
		else
			-- Seeds are on wrong node, let's kill them!
			minetest.remove_node(pos)
		end
	end
})


minetest.register_abm({
	label = "Update seasonal grass clump / tropical grass color",
	nodenames = {"group:grass_clump", "group:junglegrass"},
	interval = 5,
	chance = 20,
	action = function(pos, node)
		local old_param2 = node.param2
		local new_param2 = hades_seasons.get_seasonal_palette_color_param2(old_param2)

		if new_param2 ~= old_param2 then
			minetest.set_node(pos, {name = node.name, param2 = new_param2})
		end
	end
})

minetest.register_abm({
	label = "Update grass clump height",
	nodenames = {"group:grass_clump"},
	interval = 20,
	chance = 40,
	action = function(pos, node)
		-- The grass clump height is determined by season, surface
		-- and light.
		-- Seasons determine the max height the grass clump can have.
		-- To grow, the correct surface type and light level is required.
		-- If the grass clump is too big for the current season or
		-- it was placed on a low-quality surface, it loses height.
		-- If the grass was placed on a surface it can't live on at
		-- all, it dies (dead grass).
		local size = minetest.get_item_group(node.name, "grass_clump")
		local oldsize = size
		-- Season-based max height
		local maxsize = 5
		local season = hades_seasons.get_season()
		if season == hades_seasons.SEASON_SPRING then
			maxsize = 3
		elseif season == hades_seasons.SEASON_FALL then
			maxsize = 2
		end
		-- Check light and surface node
		local light = minetest.get_node_light(pos)
		local pos_surface = {x=pos.x,y=pos.y-1,z=pos.z}
		local node_surface = minetest.get_node(pos_surface)
		local rating = get_grass_surface_level(node_surface.name)
		-- Update grass stage depending on surface and light
		if (rating == RATE_BAD) then
			local dsize
			if size == 1 then
				dsize = 2
			else
				dsize = 4
			end
			-- Become dead grass
			minetest.set_node(pos, {name="hades_grass:dead_grass_"..size, param2 = 0})
			return
		elseif (size > maxsize or rating == RATE_MED) and size > 1 then
			-- Reduce size
			size = size - 1
		elseif size < maxsize and light >= 8 and rating == RATE_GOOD then
			-- Increase size
			size = size + 1
		end
		if oldsize ~= size then
			minetest.set_node(pos, {name="hades_grass:grass_"..size, param2 = node.param2})
			return
		end
	end
})

minetest.register_abm({
	label = "Grow tropical grass",
	nodenames = {"group:junglegrass"},
	interval = 20,
	chance = 40,
	action = function(pos, node)
		local size = minetest.get_item_group(node.name, "junglegrass")
		local oldsize = size
		-- Check light and surface node
		local light = minetest.get_node_light(pos)
		local pos_surface = {x=pos.x,y=pos.y-1,z=pos.z}
		local node_surface = minetest.get_node(pos_surface)
		local rating = get_grass_surface_level(node_surface.name)
		-- Update tropical grass stage depending on surface and light
		if (rating == RATE_BAD) then
			-- Become dead grass
			minetest.set_node(pos, {name="hades_grass:dead_grass_"..size, param2 = 0})
			return
		elseif (size == 2 and rating == RATE_MED) then
			size = 1
		elseif size == 1 and light >= 8 and rating == RATE_GOOD then
			size = 2
		end
		if oldsize ~= size then
			minetest.set_node(pos, {name="hades_grass:junglegrass_"..size, param2 = node.param2})
			return
		end
	end
})

-- Called by the grass spreading ABM, parameters are the same as
-- the ABM's `action` argument.
-- This function can be overridden by external mods if they depending on this mod.
hades_grass.grass_spread = function(pos, node, active_object_count, active_object_count_wider)
	local season = hades_seasons.get_season()
	if season == hades_seasons.SEASON_SUMMER then
		-- In summer, grass spread is less
		-- likely to occur, so we cancel the ABM with a rundom chance
		if math.random(1, 4) == 4 then
			return
		end
	elseif season ~= hades_seasons.SEASON_SPRING then
		return
	end
	pos.y = pos.y - 1
	local under = minetest.get_node(pos)
	pos.y = pos.y + 1
	if under.name ~= "hades_core:dirt_with_grass" then
		return
	end

	local light = minetest.get_node_light(pos)
	if not light or light < 8 then
		return
	end

	local pos0 = {x=pos.x-4,y=pos.y-4,z=pos.z-4}
	local pos1 = {x=pos.x+4,y=pos.y+4,z=pos.z+4}

	local hades_grasses = minetest.find_nodes_in_area(pos0, pos1, "group:grass_spread")
	if #hades_grasses > 5 then
		return
	end

	local seedlings = minetest.find_nodes_in_area(pos0, pos1, "hades_core:dirt_with_grass")
	if #seedlings > 0 then
		local seedling_pos = seedlings[math.random(#seedlings)]
		seedling_pos.y = seedling_pos.y + 1
		light = minetest.get_node_light(seedling_pos)
		if not light or light < 8 then
			return
		end
		if minetest.get_node(seedling_pos).name == "air" then
			-- Place plant of the lowest stage
			local newnode = hades_groundplants.get_new_stage(node.name, 1)
			if newnode then
				minetest.set_node(seedling_pos, {name=newnode})
			end
		end
	end
end

minetest.register_abm({
	label = "Grass spreading",
	nodenames = {"group:grass_spread"},
	neighbors = {"hades_core:dirt_with_grass"},
	interval = 60,
	chance = 30,
	action = function(pos, node, active_object_count, active_object_count_wider)
		hades_grass.grass_spread(pos, node, active_object_count, active_object_count_wider)
	end,
})

minetest.register_craft({
	output = 'hades_grass:seed_grass',
	recipe = {
		{'hades_core:mossycobble'},
		{'hades_core:mossycobble'},
		{'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_grass:seed_grass',
	recipe = {
		{'hades_core:mossytuff'},
		{'hades_core:mossytuff'},
		{'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_grass:seed_grass 2',
	recipe = {{'hades_grass:grass_1'}},
})


minetest.register_craft({
	output = 'hades_grass:seed_junglegrass',
	recipe = {
		{'hades_grass:grass_1'},
		{'hades_core:dirt'},
	}
})

minetest.register_craft({
	output = 'hades_grass:seed_junglegrass 2',
	recipe = {
		{'hades_grass:junglegrass_2'},
	}
})

minetest.register_craft({
	type = "fuel",
	recipe = "group:grass_clump",
	burntime = 2,
})
minetest.register_craft({
	type = "fuel",
	recipe = "group:dead_grass_clump",
	burntime = 2,
})
minetest.register_craft({
	type = "fuel",
	recipe = "group:junglegrass",
	burntime = 2,
})

do
	minetest.override_item("hades_core:dirt_with_grass", {
		drop = {
			items = {
				{ items = { "hades_grass:seed_grass" }, rarity = 8 },
				{ items = { "hades_grass:seed_grass" }, rarity = 8 },
				{ items = { "hades_core:dirt" } },
			},
		}
	})
end

minetest.register_alias("hades_core:grass_1", "hades_grass:grass_1")
minetest.register_alias("hades_core:grass_2", "hades_grass:grass_2")
minetest.register_alias("hades_core:grass_3", "hades_grass:grass_3")
minetest.register_alias("hades_core:grass_4", "hades_grass:grass_4")
minetest.register_alias("hades_core:grass_5", "hades_grass:grass_5")
minetest.register_alias("hades_core:junglegrass", "hades_grass:junglegrass_2")
minetest.register_alias("hades_grass:junglegrass", "hades_grass:junglegrass_2")

