local has_snowdrift = minetest.get_modpath("snowdrift") and snowdrift.get_precip
local has_regional_weather = minetest.get_modpath("regional_weather")

local well_capacity = 300 -- 10 units = 1 bucket
local barrel_capacity = 100
local well_interval = 10 -- In seconds
local barrel_interval = 2

-- If you use snowdrift (and a version which provides get_precip),
-- Then rain barrels fill MUCH more quickly than wells, but only in the rain.
-- Otherwise, they're only twice as fast.
-- Similar rules apply with regional_weather
if has_snowdrift or has_regional_weather then
	barrel_interval = 6
end

minetest.override_item("default:water_source", {
	liquid_renewable = false,
})

minetest.override_item("default:water_flowing", {
	liquid_renewable = false,
})

local bucket_map = {}
bucket_map["bucket:bucket_empty"] = "bucket:bucket_water"
if minetest.get_modpath("wooden_bucket") then
	bucket_map["wooden_bucket:bucket_wood_empty"] = "wooden_bucket:bucket_wood_water"
end

-- From: https://github.com/t-affeldt/climate_api/issues/7#issuecomment-1439351874
-- edited because there is already a daylight check
local function is_raining(pos)
	local humidity = climate_api.environment.get_humidity(pos)
	return humidity >= 50
end

local function barrel_drain(pos,_,player)
	local name = player:get_player_name()
	if minetest.is_protected(pos, name) 
		and not minetest.check_player_privs(name, {protection_bypass=true}) 
	then return end
	
	local meta = minetest.get_meta(pos)
	local water = meta:get_float("water") or 0.0
	local wielded = player:get_wielded_item():get_name()
	if not (bucket_map[wielded]) then
		return
	end
	if water >= 10 then --Code copied from buckets
		water = water - 10
		local item_count = player:get_wielded_item():get_count()
		local giving_back = bucket_map[wielded]
		if item_count > 1 then
			local water_bucket = bucket_map[wielded]

			-- if space in inventory add filled bucked, otherwise drop as item
			local inv = player:get_inventory()
			if inv:room_for_item("main", {name=water_bucket}) then
				inv:add_item("main", water_bucket)
			else
				local pos = player:getpos()
				pos.y = math.floor(pos.y + 0.5)
				minetest.add_item(pos, water_bucket)
			end

			-- set to return empty buckets minus 1
			giving_back = wielded .. " "..tostring(item_count-1)
		end
		player:set_wielded_item(giving_back)
		meta:set_float("water", water)
	else
		minetest.chat_send_player(name, "There's not enough water in this container to fill a bucket.")
	end
	meta:set_string("infotext", "Amount: " .. tostring(water / 10) .. " buckets")
end

local function barrel_fill(pos,capacity)
	local meta = minetest.get_meta(pos)
	local water = meta:get_float("water") or 0
	local raise = 1
	if (water + raise) < capacity then 
		water = water + raise
	else
		water = capacity
	end
	meta:set_float("water", water)
	meta:set_string("infotext", "Amount: " .. tostring(water / 10) .. " buckets")
end

minetest.register_node("rainbarrel:well", {
	description = "Well",
	drawtype = "mesh",
	mesh = "rainbarrel_well.obj",
	paramtype = "light",
	groups = {cracky=3},
	tiles = {minetest.registered_nodes["default:water_source"].tiles[1],"default_wood.png","default_stone.png","default_cobble.png"},
	collision_box = {type="fixed", fixed={-0.6,-0.5,-0.6,0.6,1.0,0.6}},
	selection_box = {type="fixed", fixed={-0.6,-0.5,-0.6,0.6,1.0,0.6}},
	use_texture_alpha = "opaque",  -- 'blend' causes z-fighting
	on_timer = function(pos)
		barrel_fill(pos, well_capacity)
		minetest.get_node_timer(pos):start(well_interval)
	end,
	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		meta:set_string("infotext", "Amount: 0 buckets")
		minetest.get_node_timer(pos):start(well_interval)
	end,
	on_punch = barrel_drain,
	_tt_help = "Fills with water over time" .. "\n" ..
	           "Use a bucket to obtain water"
})

minetest.register_node("rainbarrel:barrel", {
	description = "Rain Barrel",
	drawtype = "nodebox",
	node_box = {type="fixed",
		fixed = {
			{-0.375,-0.5,-0.375,0.375,0.5,0.375},
			{-0.0625,-0.4375,-0.375,0.0625,-0.3125,-0.5}
		}	
	},
	paramtype = "light",
	paramtype2 = "facedir",
	groups = {choppy=2,oddly_breakable_by_hand=1},
	tiles = {"rainbarrel_top.png","rainbarrel_top.png^[transformR180","rainbarrel_side.png","rainbarrel_side.png","rainbarrel_side.png","rainbarrel_front.png"},
	use_texture_alpha = "clip",
	on_punch = barrel_drain,
	on_place = minetest.rotate_node,
	on_timer = function(pos)
		local canfill = (minetest.get_node_light({x=pos.x,y=pos.y+1,z=pos.z}, 0.5) == 15)
		if canfill and has_snowdrift then
			if snowdrift.get_precip(pos) ~= "rain" then
				canfill = false
			end
		elseif canfill and has_regional_weather then
			canfill = is_raining(pos)
		end
		if canfill then
			barrel_fill(pos, barrel_capacity)
		end
		minetest.get_node_timer(pos):start(barrel_interval)
	end,
	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		meta:set_string("infotext", "Amount: 0 buckets")
		minetest.get_node_timer(pos):start(barrel_interval)
	end,
	on_rotate = false,
	_tt_help = "Fills with water only when it is raining" .. "\n" ..
	           "Use a bucket to obtain water"
})

local w = "group:wood"
local c = "default:cobble"
local b = ""
if minetest.get_modpath("wooden_bucket") then
	b = "wooden_bucket:bucket_wood_empty"
else
	b = "bucket:bucket_empty"
end
minetest.register_craft({
	output="rainbarrel:barrel",
	recipe={
	{w,"",w},
	{w,b,w},
	{w,w,w},
	}
	
})

minetest.register_craft({
	output="rainbarrel:well",
	recipe={
	{w,w,w},
	{c,b,c},
	{c,"",c},
	}
	
})
