-- LUALOCALS < ---------------------------------------------------------
local klots, math, minetest, vector
    = klots, math, minetest, vector
local math_atan2, math_pi
    = math.atan2, math.pi
-- LUALOCALS > ---------------------------------------------------------

local modstore = minetest.get_mod_storage()

local emerge_radius = 31
emerge_radius = {x = emerge_radius, y = emerge_radius, z = emerge_radius}

local vector_equals = vector.equals
local vector_round = vector.round
local hash = minetest.hash_node_position

local function setfocus(player, pos)
	local key = hash(vector_round(pos))
	local focpos = minetest.find_node_near(pos, 15, "group:camera_focus", true)
	if focpos then
		modstore:set_string(key, minetest.serialize(focpos))
		if not klots.editmode then minetest.remove_node(focpos) end
	else
		focpos = modstore:get_string(key)
		focpos = focpos and focpos ~= "" and minetest.deserialize(focpos)
		if not focpos then return end
	end
	pos = {x = pos.x, y = pos.y + player:get_properties().eye_height, z = pos.z}
	local diff = vector.subtract(focpos, pos)
	player:set_look_horizontal(math_atan2(diff.z, diff.x) - math_pi / 2)
	player:set_look_vertical(math_atan2(-diff.y, vector.length({x = diff.x, y = 0, z = diff.z})))
end

local getdata = klots.register_playerstep(function(player, data, dtime)
		if not (data.waitpos and data.topos) then return end
		local loaded = (not data.loading) and minetest.get_node_or_nil(data.topos)
		if loaded and data.cd and data.cd <= 0 then
			if vector_equals(vector_round(player:get_pos()), vector_round(data.topos)) then
				local control = data.topos.control
				if control == nil then
					control = data.topos.y >= 10000 and "frozen"
					or data.topos.y >= 128 and "zerograv"
					or false
				end
				klots.player_control_set(player, control)
				klots.flash_screen(player, "#000000")
				data.cd = nil
				data.waitpos = nil
				data.topos = nil
			else
				klots.player_control_apply(player, function(obj)
						obj:set_pos(data.topos)
						obj:set_velocity({x = 0, y = 0, z = 0})
					end)
				setfocus(player, data.topos)
			end
		else
			data.cd = (data.cd or 2) - dtime
			if not loaded then
				if not data.loading then
					data.loading = true
					minetest.emerge_area(
						vector.subtract(data.topos, emerge_radius),
						vector.add(data.topos, emerge_radius),
						function(_, _, rem)
							data.loading = rem > 0 or nil
						end)
				end
			end
			klots.player_control_set(player, "frozen")
			klots.player_control_apply(player, function(obj)
					obj:set_pos(data.waitpos)
					obj:set_velocity({x = 0, y = 0, z = 0})
				end)
			klots.flash_screen(player, "#000000", true)
		end
	end)

function klots.player_teleport(player, waitpos, topos)
	local data = getdata(player)
	data.waitpos = waitpos
	data.topos = topos
end
