-- LUALOCALS < ---------------------------------------------------------
local get_mod_api, ipairs, math, minetest
    = get_mod_api, ipairs, math, minetest
local math_ceil
    = math.ceil
-- LUALOCALS > ---------------------------------------------------------

local api = get_mod_api()
local modname = minetest.get_current_modname()

------------------------------------------------------------------------

local function mktile(qty)
	if qty <= 0 then return "[combine:1x1" end
	qty = math_ceil(qty * 32) * 8
	return "[combine:1x1^[noalpha"
	.. (qty < 255 and ("^[opacity:" .. qty) or "")
end

------------------------------------------------------------------------

do
	local seen = {}
	local tiles = {}
	local idx = 0
	local function flush()
		if #tiles < 1 then return end
		idx = idx + 1
		minetest.register_node(modname .. ":preload" .. idx, {
				tiles = tiles,
				groups = {not_in_creative_inventory = 1}
			})
		tiles = {}
	end
	for i = 0, 1, 1/32 do
		local tile = mktile(i)
		if not seen[tile] then
			seen[tile] = true
			tiles[#tiles + 1] = tile
		end
		if #tiles >= 6 then flush() end
	end
	flush()
end

------------------------------------------------------------------------

local function sethudnow(player, data, dtime)
	local qty = 0
	if data.qty then
		qty = data.qty - data.rate * dtime
		data.qty = qty > 0 and qty or nil
	end
	local tile = mktile(qty)

	if tile ~= data.tile then
		if data.hudid then
			player:hud_change(data.hudid, "text", tile)
		else
			data.hudid = player:hud_add({
					hud_elem_type = "image",
					position = {x = 0.5, y = 0.5},
					text = tile,
					direction = 0,
					scale = {x = -105, y = -105},
					offset = {x = 0, y = 0},
					z_index = 1000
				})
		end
		data.tile = tile
	end
end

local getdata = api.create_player_data()
minetest.register_globalstep(function(dtime)
		for _, player in ipairs(minetest.get_connected_players()) do
			sethudnow(player, getdata(player), dtime)
		end
	end)

function api.screenfade(player, duration, opacity)
	duration = duration or 3
	opacity = opacity or 1.5
	player = player or api.mainplayer()
	if not player then return end
	local data = getdata(player)
	if duration == true then
		data.qty = opacity
		data.rate = 0
	elseif opacity <= 0 or duration <= 0 then
		data.qty = nil
	else
		data.qty = opacity
		data.rate = opacity / duration
	end
	sethudnow(player, getdata(player), 0)
end
