local S = minetest.get_translator("hades_flowers")

hades_flowers = {}

-- See README.txt for licensing and other information.

-- Time intervals throughout the year, used to determine
-- when flowers grow and bloom.
local TIME_SPRING_SUMMER = 0 -- spring and summer
local TIME_SUMMER_FALL = 1 -- summer and fall
local TIME_FALL_SPRING = 2 -- fall and spring
local TIME_SPRING_START = 3 -- first day of spring (1 day)
local TIME_SUMMER_MIDDLE = 4 -- middle of summer (1 day)
local TIME_FALL_QUARTER = 5 -- first quarter of fall (1 day)

-- Surface types
local SURFACE_DIRT_CLAY = 0 -- dirt and clay
local SURFACE_ASH_SAND_DIRT = 1 -- ash, sand and dirt

-- Calculate the middle day of a season
local SEASON_MIDDLE_DAY = math.max(0, math.floor(hades_seasons.SEASON_LENGTH / 2) - 1)
-- Calculate the "quarter" day of a season
local SEASON_QUARTER_DAY = math.max(0, math.floor(hades_seasons.SEASON_LENGTH / 4))

local LIGHT_MIN = 8

local flowers = {
	-- Base flowers (common)
	{ "white", S("White Flower"), S("White Flower Seedling"), S("White Flower Seed"), { -0.15, -0.5, -0.15, 0.15, 0.2, 0.15 }, { -0.15, -0.5, -0.15, 0.15, 0, 0.15 }},
	{ "red", S("Red Flower"), S("Red Flower Seedling"), S("Red Flower Seed"), { -0.15, -0.5, -0.15, 0.15, 0.3, 0.15 }, { -0.15, -0.5, -0.15, 0.15, 0, 0.15 } },
	{ "orange",
		--~ A flower that has the color orange
		S("Orange Flower"),
		--~ A seedling for a flower that has the color orange
		S("Orange Flower Seedling"),
		--~ Seed for a flower that has the color orange
		S("Orange Flower Seed"), { -0.15, -0.5, -0.15, 0.15, 0.25, 0.15 }, { -0.15, -0.5, -0.15, 0.15, 0, 0.15 }},
	{ "yellow", S("Yellow Flower"), S("Yellow Flower Seedling"), S("Yellow Flower Seed"), { -0.27, -0.5, -0.27, 0.27, 0.2, 0.27 }, { -0.15, -0.5, -0.15, 0.15, 0, 0.15 } },
	{ "blue", S("Blue Flower"), S("Blue Flower Seedling"), S("Blue Flower Seed"), { -0.175, -0.5, -0.175, 0.175, 0.35, 0.175 }, { -0.15, -0.5, -0.15, 0.15, 0, 0.15 } },
	{ "violet", S("Violet Flower"), S("Violet Flower Seedling"), S("Violet Flower Seed"), { -0.15, -0.5, -0.15, 0.15, 0.2, 0.15 }, { -0.15, -0.5, -0.15, 0.15, 0, 0.15 } },

	{ "grey", S("Grey Flower"), S("Grey Flower Seedling"), S("Grey Flower Seed"), { -0.27, -0.5, -0.27, 0.27, 7/16, 0.27 }, { -0.15, -0.5, -0.15, 0.15, -1/16, 0.15 }, TIME_FALL_SPRING, nil, SURFACE_ASH_SAND_DIRT },

	-- Special flowers (rare / difficult to grow)
	{ "pink", S("Pink Flower"), S("Pink Flower Seedling"), S("Pink Flower Seed"), { -5/16, -0.5, -5/16, 5/16, 5/16, 5/16 }, { -4/16, -0.5, -4/16, 4/16, -1/16, 4/16 }, TIME_SPRING_START, TIME_FALL_SPRING },
	{ "cyan", S("Cyan Flower"), S("Cyan Flower Seedling"), S("Cyan Flower Seed"), { -5/16, -0.5, -5/16, 5/16, 0.5, 5/16 }, { -4/16, -0.5, -4/16, 4/16, -4/16, 4/16 }, TIME_SUMMER_MIDDLE, TIME_SPRING_SUMMER },
	{ "magenta", S("Magenta Flower"), S("Magenta Flower Seedling"), S("Magenta Flower Seed"), { -6/16, -0.5, -6/16, 6/16, 0.5, 6/16 }, { -4/16, -0.5, -4/16, 4/16, -2/16, 4/16 }, TIME_FALL_QUARTER, TIME_SUMMER_FALL },
}

for f=1, #flowers do
	local color = flowers[f][1]
	local desc_flower = flowers[f][2]
	local desc_seedling = flowers[f][3]
	local desc_seed = flowers[f][4]
	local selbox_flower = flowers[f][5]
	local selbox_seedling = flowers[f][6]
	local bloom_season = flowers[f][7] or TIME_SPRING_SUMMER
	local grow_season = flowers[f][8] or TIME_SPRING_SUMMER
	local surface = flowers[f][9] or SURFACE_DIRT_CLAY

	local bloom_txt, g_spread
	if bloom_season == TIME_SPRING_START then
		bloom_txt = S("Blooms in the first day of spring")
	elseif bloom_season == TIME_SUMMER_MIDDLE then
		bloom_txt = S("Blooms in summer solstice")
	elseif bloom_season == TIME_FALL_QUARTER then
		bloom_txt = S("Blooms in day @1 of fall", SEASON_QUARTER_DAY+1)
	elseif bloom_season == TIME_SPRING_SUMMER then
		bloom_txt = S("Blooms in spring and summer")
		g_spread = 1
	elseif bloom_season == TIME_SUMMER_FALL then
		bloom_txt = S("Blooms in summer and fall")
		g_spread = 1
	elseif bloom_season == TIME_FALL_SPRING then
		bloom_txt = S("Blooms in fall and spring")
		g_spread = 1
	else
		bloom_txt = ""
		minetest.log("error", "[hades_flowers] Flower uses unsupported bloom season: "..tostring(bloom_season))
	end
	local grow_txt
	if grow_season == bloom_season then
		if grow_season == TIME_SPRING_SUMMER then
			grow_txt = S("Seasons: Spring, Summer")
		elseif grow_season == TIME_SUMMER_FALL then
			grow_txt = S("Seasons: Summer, Fall")
		elseif grow_season == TIME_FALL_SPRING then
			grow_txt = S("Seasons: Fall, Spring")
		end
	else
		if grow_season == TIME_SPRING_SUMMER then
			grow_txt = S("Grows in spring and summer")
		elseif grow_season == TIME_SUMMER_FALL then
			grow_txt = S("Grows in summer and fall")
		elseif grow_season == TIME_FALL_SPRING then
			grow_txt = S("Grows in fall and spring")
		end
	end
	if not grow_txt then
		grow_txt = ""
		minetest.log("error", "[hades_flowers] Flower "..color.." uses unknown grow season: "..tostring(grow_season))
	end

	local surface_txt_1, surface_txt_2
	if surface == SURFACE_ASH_SAND_DIRT then
		surface_txt_1 = S("Grows on ash or sand or dirt in light")
		surface_txt_2 = S("Lives on ash, sand or dirt")
	else
		surface_txt_1 = S("Grows on dirt in light")
		surface_txt_2 = S("Lives on dirt or clay")
	end

	hades_groundplants.register_groundplant("hades_flowers", color, {
		description = desc_flower,
		stages = {
			{
				description = desc_seedling,
				_tt_help = surface_txt_1.."\n"..bloom_txt,
				tiles = { "hades_flowers_seedling_"..color..".png" },
				image = "hades_flowers_seedling_"..color..".png",
				selection_box = {
					type = "fixed",
					fixed = selbox_seedling,
				},
				in_creative_inventory = false,
			},
			{
				description = desc_flower,
				_tt_help = surface_txt_2.."\n"..bloom_txt,
				tiles = { "hades_flowers_"..color..".png" },
				image = "hades_flowers_"..color..".png",
				selection_box = {
					type = "fixed",
					fixed = selbox_flower,
				},
				extra_groups = { flower_spread = g_spread },
				in_creative_inventory = true,
			},
		},
		sounds = hades_sounds.node_sound_grass_defaults(),
		groups = {snappy=3, flammable=2, attached_node=1, ["color_"..color]=1 },
		stage_groups = { "flower" },
	})

	local seed_txt
	if grow_season == bloom_season then
		seed_txt = grow_txt
	else
		seed_txt = grow_txt.."\n"..bloom_txt
	end
	hades_seeds.register_seed("hades_flowers:seed_"..color, {
		description = desc_seed,
		_tt_help = surface_txt_1.."\n"..seed_txt,
		image = "hades_flowers_seed_"..color..".png",
		surface_check = function(node)
			if node.name == "hades_furniture:plant_pot" then
				return true
			end
			if surface == SURFACE_ASH_SAND_DIRT then
				return minetest.get_item_group(node.name, "dirt") ~= 0 or
						minetest.get_item_group(node.name, "sand") ~= 0 or
						minetest.get_item_group(node.name, "ash") ~= 0
			else
				return minetest.get_item_group(node.name, "dirt") ~= 0 or node.name == "hades_furniture:plant_pot"
			end
		end,
		extra_groups = { seed_flower = 1 },
		_hades_grows_to = "hades_flowers:"..color.."_1",
	})
end

minetest.register_node("hades_flowers:dead", {
	description = S("Dead Flower"),
	drawtype = "plantlike",
	tiles = { "hades_flowers_dead.png" },
	use_texture_alpha = "clip",
	inventory_image = "hades_flowers_dead.png",
	wield_image = "hades_flowers_dead.png",
	waving = 1,
	sunlight_propagates = true,
	paramtype = "light",
	walkable = false,
	buildable_to = true,
	floodable = true,
	groups = {snappy=3, flammable=2, attached_node=1},
	sounds = hades_sounds.node_sound_grass_defaults(),
	drop = "",
	selection_box = {
		type = "fixed",
		fixed = { -0.15, -0.5, -0.15, 0.15, 0, 0.15 },
	},
})

minetest.register_abm({
	label = "Grow flower seeds and seedlings in light",
	nodenames = {"group:seed_flower", "group:flower"},
	interval = 10,
	chance = 25,
	action = function(pos, node)
		local light = minetest.get_node_light(pos)
		if light < LIGHT_MIN then
			return
		end
		local g_seed = minetest.get_item_group(node.name, "seed_flower")
		local g_flower = minetest.get_item_group(node.name, "flower")

		local split = node.name:split(":")
		local mname = split[1]
		local pname = split[2]

		local bloom_season, grow_season, surface
		for f=1, #flowers do
			local pname_s
			if g_seed == 0 then
				pname_s = string.sub(pname, 1, -3)
			else
				pname_s = string.sub(pname, 6, -1)
			end
			if flowers[f][1] == pname_s then
				bloom_season = flowers[f][7]
				grow_season = flowers[f][8]
				surface = flowers[f][9]
				break
			end
		end
		if not bloom_season then
			bloom_season = TIME_SPRING_SUMMER
		end
		if not grow_season then
			grow_season = TIME_SPRING_SUMMER
		end
		if not surface then
			surface = SURFACE_DIRT_CLAY
		end

		local below = {x=pos.x, y=pos.y-1, z=pos.z}
		local bnode = minetest.get_node(below)

		-- Die if neither on correct surface or plant pot
		local die
		local on_soil = false
		-- Plant always survives on plant pot
		if bnode.name ~= "hades_furniture:plant_pot" then
			if surface == SURFACE_DIRT_CLAY then
				if minetest.get_item_group(bnode.name, "dirt") ~= 0 then
					on_soil = true
				else
					if bnode.name ~= "hades_core:clay" then
						die = true
					end
				end
			elseif surface == SURFACE_ASH_SAND_DIRT then
				if minetest.get_item_group(bnode.name, "ash") ~= 0 and minetest.get_item_group(bnode.name, "sans") ~= 0 and minetest.get_item_group(bnode.name, "dirt") ~= 0 then
					die = true
				else
					on_soil = true
				end
			end
		else
			on_soil = true
		end
		if die then
			if g_flower ~= 0 then
				minetest.set_node(pos, {name="hades_flowers:dead"})
			else
				minetest.remove_node(pos)
			end
			return
		end

		local is_in_season = function(lseason, lday, timeframe)
			-- Spring or summer
			if (timeframe == TIME_SPRING_SUMMER and (lseason == hades_seasons.SEASON_SPRING or lseason == hades_seasons.SEASON_SUMMER)) or
					-- Summer or fall
					(timeframe == TIME_SUMMER_FALL and (lseason == hades_seasons.SEASON_SUMMER or lseason == hades_seasons.SEASON_FALL)) or
					-- Fall or spring
					(timeframe == TIME_FALL_SPRING and (lseason == hades_seasons.SEASON_FALL or lseason == hades_seasons.SEASON_SPRING)) or
					-- First day of spring
					(timeframe == TIME_SPRING_START and lseason == hades_seasons.SEASON_SPRING and lday == 0) or
					-- Summer solstice (Middle day of summer)
					(timeframe == TIME_SUMMER_MIDDLE and lseason == hades_seasons.SEASON_SUMMER and lday == SEASON_MIDDLE_DAY) or
					-- Quarter day of fall
					(timeframe == TIME_FALL_QUARTER and lseason == hades_seasons.SEASON_FALL and lday == SEASON_QUARTER_DAY) then
				return true
			else
				return false
			end
		end

		local season = hades_seasons.get_season()
		local day = hades_seasons.get_day_in_season()

		local in_bloom_season = is_in_season(season, day, bloom_season)
		local in_grow_season = is_in_season(season, day, grow_season)

		if g_seed ~= 0 then
			-- Grow seed in grow season
			if on_soil and in_grow_season then
				local fname = mname .. ":" .. pname:gsub("seed_", "")
				fname = fname .. "_1"
				local below = {x=pos.x, y=pos.y-1, z=pos.z}
				local bnode = minetest.get_node(below)
				minetest.set_node(pos, {name = fname, param2 = 0})
			end
		elseif g_flower == 1 then
			-- Grow seedling to flower when in bloom season
			if on_soil and in_bloom_season then
				local fname = mname .. ":" .. pname:gsub("_%d+", "")
				fname = fname .. "_2"
				minetest.set_node(pos, {name = fname, param2 = 0})
			end
		elseif g_flower == 2 then
			-- Return flower to seedling stage when out of bloom season
			-- (it can bloom again when it's the bloom season again).
			local fname = mname .. ":" .. pname:gsub("_%d+", "")
			fname = fname .. "_1"
			if not in_bloom_season then
				minetest.set_node(pos, {name = fname, param2 = 0})
			end
		end
	end
})

-- Called by the flower 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_flowers.flower_spread = function(pos, node, active_object_count, active_object_count_wider)
	if hades_seasons.get_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 < LIGHT_MIN 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_flowers = minetest.find_nodes_in_area(pos0, pos1, "group:flower_spread")
	if #hades_flowers > 3 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 < LIGHT_MIN then
			return
		end
		if minetest.get_node(seedling_pos).name == "air" then
			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 = "Flower spreading",
	nodenames = {"group:flower_spread"},
	neighbors = {"hades_core:dirt_with_grass"},
	interval = 50,
	chance = 30,
	action = function(pos, node, active_object_count, active_object_count_wider)
		hades_flowers.flower_spread(pos, node, active_object_count, active_object_count_wider)
	end,
})

minetest.register_craft({
	output = 'hades_flowers:seed_grey',
	recipe = {
		{'hades_trees:pale_seed', 'hades_trees:pale_seed', 'hades_trees:pale_seed'},
		{'hades_grass:dead_grass_1', 'hades_grass:dead_grass_1', 'hades_grass:dead_grass_1'},
		{'hades_core:ash', 'hades_core:ash', 'hades_core:ash'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_white',
	recipe = {
		{'hades_farming:seed_cotton', 'hades_farming:seed_cotton', 'hades_farming:seed_cotton'},
		{'hades_grass:grass_1', 'hades_grass:grass_1', 'hades_grass:grass_1'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_yellow',
	recipe = {
		{'hades_flowers:white', 'hades_flowers:white', 'hades_flowers:white'},
		{'hades_grass:grass_1', 'hades_core:gold_lump', 'hades_grass:grass_1'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_red',
	recipe = {
		{'hades_flowers:white', 'hades_flowers:white', 'hades_flowers:white'},
		{'hades_grass:grass_1', 'hades_core:ruby', 'hades_grass:grass_1'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_violet',
	recipe = {
		{'hades_flowers:red', 'hades_flowers:red', 'hades_flowers:red'},
		{'hades_flowers:blue', 'hades_flowers:blue', 'hades_flowers:blue'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_blue',
	recipe = {
		{'hades_flowers:white', 'hades_flowers:white', 'hades_flowers:white'},
		{'hades_grass:grass_1', 'hades_core:sapphire', 'hades_grass:grass_1'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_orange',
	recipe = {
		{'hades_flowers:yellow', 'hades_flowers:yellow', 'hades_flowers:yellow'},
		{'hades_flowers:red', 'hades_flowers:red', 'hades_flowers:red'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_pink',
	recipe = {
		{'hades_flowers:white', 'hades_flowers:white', 'hades_flowers:white'},
		{'hades_flowers:red', 'hades_flowers:red', 'hades_flowers:red'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_cyan',
	recipe = {
		{'hades_flowers:white', 'hades_flowers:white', 'hades_flowers:white'},
		{'hades_flowers:blue', 'hades_flowers:blue', 'hades_flowers:blue'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
minetest.register_craft({
	output = 'hades_flowers:seed_magenta',
	recipe = {
		{'hades_flowers:violet', 'hades_flowers:violet', 'hades_flowers:violet'},
		{'hades_flowers:red', 'hades_flowers:red', 'hades_flowers:red'},
		{'hades_core:dirt', 'hades_core:dirt', 'hades_core:dirt'},
	}
})
-- Aliases for original flowers mod
minetest.register_alias("flowers:dandelion_white", "hades_flowers:white_2")
minetest.register_alias("flowers:dandelion_yellow", "hades_flowers:yellow_2")
minetest.register_alias("flowers:geranium", "hades_flowers:blue_2")
minetest.register_alias("flowers:rose", "hades_flowers:red_2")
minetest.register_alias("flowers:tulip", "hades_flowers:orange_2")
minetest.register_alias("flowers:viola", "hades_flowers:violet_2")
-- Aliases for old version of hades_flowers
minetest.register_alias("hades_flowers:white", "hades_flowers:white_2")
minetest.register_alias("hades_flowers:yellow", "hades_flowers:yellow_2")
minetest.register_alias("hades_flowers:blue", "hades_flowers:blue_2")
minetest.register_alias("hades_flowers:red", "hades_flowers:red_2")
minetest.register_alias("hades_flowers:orange", "hades_flowers:orange_2")
minetest.register_alias("hades_flowers:violet", "hades_flowers:violet_2")

