local well_capacity = 20.0 --Units are amount of buckets fillable
local barrel_capacity = 5.0
local well_interval = 2400 --In seconds
local barrel_interval = 1200

-- 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.
if core.global_exists("snowdrift") then
	if snowdrift.get_precip then
		barrel_interval = 300
	end
end

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

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


local function barrel_drain(pos, _, player)
	local name = player:get_player_name()
	if core.is_protected(pos, name)
		and not core.check_player_privs(name, { protection_bypass = true })
	then
		return
	end

	local meta = core.get_meta(pos)
	local water = meta:get_float("water") or 0.0
	local wielded_item = player:get_wielded_item():get_name()
	if not (wielded_item == "bucket:bucket_empty" or wielded_item == "wooden_bucket:bucket_wood_empty") then return end
	if water >= 1.0 then --Code copied from buckets
		water = water - 1.0
		local item_count = player:get_wielded_item():get_count()
		local giving_back = ""
		if wielded_item == "bucket:bucket_empty" then
			giving_back = "bucket:bucket_water"
		else
			giving_back = "wooden_bucket:bucket_wood_water"
		end
		if item_count > 1 then
			-- if space in inventory add filled bucked, otherwise drop as item
			local inv = player:get_inventory()
			if inv:room_for_item("main", { name = giving_back }) then
				inv:add_item("main", giving_back)
			else
				local ppos = player:get_pos()
				ppos.y = math.floor(ppos.y + 0.5)
				core.add_item(ppos, giving_back)
			end

			-- set to return empty buckets minus 1
			if wielded_item == "bucket:bucket_empty" then
				giving_back = "bucket:bucket_empty " .. tostring(item_count - 1)
			else
				giving_back = "wooden_bucket:bucket_wood_empty " .. tostring(item_count - 1)
			end
		end
		player:set_wielded_item(giving_back)
		meta:set_float("water", water)
	else
		core.chat_send_player(name, "There's not enough water in this container to fill a bucket.")
	end
end

local function barrel_fill(pos, capacity)
	local meta = core.get_meta(pos)
	local water = meta:get_float("water") or 0.0
	local raise = (math.random(1, 3) / 2) --0.5, 1, or 1.5
	if (water + raise) < capacity then
		water = water + raise
	else
		water = capacity
	end
	meta:set_float("water", water)
end

core.register_node("rainbarrel:well", {
	description = "Well",
	drawtype = "mesh",
	mesh = "rainbarrel_well.obj",
	paramtype = "light",
	groups = { cracky = 3 },
	tiles = { core.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 } },
	on_timer = function(pos)
		barrel_fill(pos, well_capacity)
		core.get_node_timer(pos):start(well_interval)
	end,
	on_construct = function(pos)
		core.get_node_timer(pos):start(well_interval)
	end,
	on_punch = barrel_drain,
})

core.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" },
	on_punch = barrel_drain,
	on_place = core.rotate_node,
	on_timer = function(pos)
		local canfill = (core.get_node_light({ x = pos.x, y = pos.y + 1, z = pos.z }, 0.5) == 15)
		if core.global_exists("snowdrift") then
			if canfill and snowdrift.get_precip then
				if snowdrift.get_precip(pos) ~= "rain" then
					canfill = false
				end
			end
		end
		if canfill then
			barrel_fill(pos, barrel_capacity)
		end
		core.get_node_timer(pos):start(barrel_interval)
	end,
	on_construct = function(pos)
		core.get_node_timer(pos):start(barrel_interval)
	end,
})

local w = "group:wood"
local c = "group:cobble"
local b = "group:bucket_empty"

core.register_craft({
	output = "rainbarrel:barrel",
	recipe = {
		{ w, "", w },
		{ w, b,  w },
		{ w, w,  w },
	}
})

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