local S = minetest.get_translator("hades_farming")

local DEFAULT_MINLIGHT = 8
local DEFAULT_MAXLIGHT = 15

-- Wear out hoes, place soil
hades_farming.hoe_on_use = function(itemstack, user, pointed_thing, uses)
	local pt = pointed_thing
	-- check if pointing at a node
	if not pt then
		return
	end
	if pt.type ~= "node" then
		return
	end
	
	local under = minetest.get_node(pt.under)
	local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z}
	local name = user:get_player_name()
	if minetest.is_protected(pt.under, name) and not minetest.check_player_privs(name, "protection_bypass") then
		minetest.record_protection_violation(pt.under, name)
		return itemstack
	end

	local above = minetest.get_node(p)
	
	-- return if any of the nodes is not registered
	if not minetest.registered_nodes[under.name] then
		return
	end
	if not minetest.registered_nodes[above.name] then
		return
	end
	
	-- check if the node above the pointed thing is air
	if above.name ~= "air" then
		return
	end
	
	-- check if pointing at soil
	if minetest.get_item_group(under.name, "soil") ~= 1 then
		return
	end
	
	-- check if (wet) soil defined
	local regN = minetest.registered_nodes
	if regN[under.name].soil == nil or regN[under.name].soil.wet == nil or regN[under.name].soil.dry == nil then
		return
	end
	
	-- turn the node into soil, wear out item and play sound
	minetest.set_node(pt.under, {name = regN[under.name].soil.dry})
	minetest.sound_play("default_dig_crumbly", {
		pos = pt.under,
		gain = 0.5,
	}, true)
	
	if not minetest.is_creative_enabled(name) then
		itemstack:add_wear_by_uses(uses)
	end
	return itemstack
end

-- Register new hoes
hades_farming.register_hoe = function(name, def)
	-- Check for : prefix (register new hoes in your mod's namespace)
	if name:sub(1,1) ~= ":" then
		name = ":" .. name
	end
	-- Check def table
	if def.description == nil then
		def.description = "Hoe"
	end
	if def.inventory_image == nil then
		def.inventory_image = "unknown_item.png"
	end
	if def.recipe == nil then
		def.recipe = {
			{"air","air",""},
			{"","group:stick",""},
			{"","group:stick",""}
		}
	end
	if def.max_uses == nil then
		def.max_uses = 30
	end
	-- Register the tool
	minetest.register_tool(name, {
		description = def.description,
		_tt_help = def._tt_help .. "\n" .. S("Uses: @1", def.max_uses),
		inventory_image = def.inventory_image,
		on_use = function(itemstack, user, pointed_thing)
			return hades_farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
		end
	})
	-- Register its recipe
	if def.material == nil then
		minetest.register_craft({
			output = name:sub(2),
			recipe = def.recipe
		})
	else
		local handle
		if def.material_handle then
			handle = def.material_handle
		else
			handle = "group:stick"
		end
		minetest.register_craft({
			output = name:sub(2),
			recipe = {
				{def.material, def.material, ""},
				{"", handle, ""},
				{"", handle, ""}
			}
		})
	end
end

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

-- Register plants
hades_farming.register_plant = function(name, def)


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

	-- Check def table
	if not def.description_seed then
		def.description_seed = "Seed"
	end
	if not def.inventory_image then
		def.inventory_image = "unknown_item.png"
	end
	if not def.steps then
		return nil
	end
	if not def.minlight then
		def.minlight = DEFAULT_MINLIGHT
	end
	if not def.maxlight then
		def.maxlight = DEFAULT_MAXLIGHT
	end

	if def.meshoptions then
		def.place_param2 = def.meshoptions
	end

	-- Register seed
	local g = {}
	-- Extra group to distinguish it from other seeds
	g["seed_farming"] = 1

	local surface_check = function(node)
		return minetest.get_item_group(node.name, "soil") >= 2
	end

	hades_seeds.register_seed(":" .. mname .. ":seed_" .. pname, {
		description = def.description_seed,
		_tt_help = def._tt_help,
		image = def.inventory_image,
		place_param2 = def.place_param2,
		surface_check = surface_check,
		extra_groups = g,
		seasons = def.seasons,
		_hades_grows_to = mname .. ":" .. pname .. "_1",
	})

	-- Register harvest
	minetest.register_craftitem(":" .. mname .. ":" .. pname, {
		description = def.description_harvest,
		groups = { food = 1, eatable = def.food_points },
		on_use = minetest.item_eat(def.food_points),
		inventory_image = mname .. "_" .. pname .. ".png",
	})

	-- Register growing steps
	local stages = {}
	local nodegroups = { snappy = 3, flammable = 2, not_in_creative_inventory = 1, attached_node = 1, farming_plant = 1 }
	local stage_groups = { pname }
	local description_plant
	if def.description_plant then
		description_plant = def.description_plant
	end
	for i=1,def.steps do
		local stage = {}
		stage.drop = {
			items = {
				{items = {mname .. ":seed_" .. pname}, rarity = 4 - i},
				{items = {mname .. ":seed_" .. pname}, rarity = 8 - i * 2},
				{items = {mname .. ":" .. pname}, rarity = 4 - i},
				{items = {mname .. ":" .. pname}, rarity = 6 - i},
				{items = {mname .. ":" .. pname}, rarity = 8 - i * 2},
				{items = {mname .. ":" .. pname}, rarity = 9 - i * 2},
			}
		}
		stage.tiles = { mname .. "_" .. pname .. "_" .. i .. ".png" }
		stage.selection_box = {
			type = "fixed",
			fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
		}
		local texture = mname .. "_" .. pname .. "_" .. i .. ".png"
		stage.image = texture

		table.insert(stages, stage)
	end
	hades_groundplants.register_groundplant(mname, pname, {
		description = description_plant,
		meshoptions = true,
		place_param2 = def.place_param2,
		stages = stages,
		groups = nodegroups,
		stage_groups = stage_groups,
		sounds = hades_sounds.node_sound_grass_defaults(),
		seasons = def.seasons,
	})

	-- Dead plant (e.g. when the plant dies for being out of season)
	minetest.register_node(mname..":"..pname.."_dead", {
		description = S("@1 (dead)", description_plant),
		drawtype = "plantlike",
		tiles = { mname .. "_" .. pname .. "_dead.png" },
		selection_box = {
			type = "fixed",
			fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
		},
		inventory_image = mname .. "_" .. pname .. "_dead.png",
		wield_image = mname .. "_" .. pname .. "_dead.png",
		use_texture_alpha = "clip",
		paramtype = "light",
		sunlight_propagates = true,
		paramtype2 = "meshoptions",
		place_param2 = def.place_param2,
		waving = 1,
		walkable = false,
		is_ground_content = true,
		buildable_to = true,
		floodable = true,
		drop = {
			items = {
				{items = {mname .. ":seed_" .. pname}, rarity = 3},
				{items = {mname .. ":seed_" .. pname}, rarity = 3},
				{items = {mname .. ":seed_" .. pname}, rarity = 3},
			},
		},
		groups = nodegroups,
		sounds = hades_sounds.node_sound_grass_defaults(),
	})

	-- Growing and kill ABM
	minetest.register_abm({
		label = "Grow or kill farming seeds and plants: "..pname,
		nodenames = {"group:" .. pname, "group:seed_farming"},
		interval = 93,
		chance = 12,
		action = function(pos, node)
			local split = node.name:split(":")
			local mname = split[1]
			local pname = split[2]
			pname = pname:gsub("seed_", "")
			pname = pname:gsub("_%d+", "")

			local plant_height = minetest.get_item_group(node.name, pname)

			local is_seed = minetest.get_item_group(node.name, "seed_farming") ~= 0

			local node_def = minetest.registered_nodes[node.name]
			local check_seasons
			if node_def and node_def._hades_seasons then
				check_seasons = node_def._hades_seasons
			end

			if is_in_season(check_seasons) == false then
				if is_seed then
					-- Seed refuses to grow out-of-season
					return
				else
					-- plant dies if out-of-season
					minetest.set_node(pos, {name=mname..":"..pname.."_dead", param2 = node.param2})
					return
				end
			end

			-- check ground for growth or death
			local ground_node = minetest.get_node(vector.offset(pos, 0, -1, 0))
			local soil_g = minetest.get_item_group(ground_node.name, "soil")
			if soil_g == 0 then
				-- not on soil, check for survival.
				-- Plant survives on dirt, clay and plant pot, dies otherwise
				if minetest.get_item_group(ground_node.name, "dirt") == 0 and
						ground_node.name ~= "hades_core:clay" and
						ground_node.name ~= "hades_furniture:plant_pot" then
					minetest.set_node(pos, {name=mname..":"..pname.."_dead", param2 = node.param2})
					return
				end
			elseif soil_g < 3 then
				-- not on wet soil, don't grow
				return
			end
			-- we're on wet soil, so we perform further checks

			-- return if already full grown
			if plant_height == def.steps then
				return
			end

			-- check light
			local ll = minetest.get_node_light(pos)
			if not ll or ll < def.minlight or ll > def.maxlight then
				return
			end

			-- grow
			if is_seed then
				-- grow seed
				minetest.set_node(pos, {name = mname .. ":" .. pname .. "_1", param2 = node.param2})
			else
				-- grow plant
				minetest.set_node(pos, {name = mname .. ":" .. pname .. "_" .. plant_height + 1, param2 = node.param2})
			end
		end
	})

	-- Return
	local r = {
		seed = mname .. ":seed_" .. pname,
		harvest = mname .. ":" .. pname
	}
	return r
end

