-- LUALOCALS < ---------------------------------------------------------
local error, get_mod_api, ipairs, minetest, pairs, posrel, startswith,
      string, vector
    = error, get_mod_api, ipairs, minetest, pairs, posrel, startswith,
      string, vector
local string_format, string_sub
    = string.format, string.sub
-- LUALOCALS > ---------------------------------------------------------

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

local ambnode = modname .. ":ambient"
minetest.register_node(ambnode, {
		drawtype = "airlike",
		pointable = false,
		walkable = false,
		sunlight_propagates = true,
		paramtype = "light",
		light_source = 3,
		buildable_to = true,
		air_equivalent = true,
	})
function minetest.remove_node(pos)
	return minetest.set_node(pos, {name = ambnode})
end

local allschematics = {}
api.allschematics = allschematics
do
	local modpath = minetest.get_modpath(modname)
	local schempath = modpath .. "/schematics"
	for _, fn in pairs(minetest.get_dir_list(schempath, false)) do
		if string_sub(fn, -4) == ".mts" then
			allschematics[string_sub(fn, 1, -5)] = {
				mts = minetest.register_schematic(schempath .. "/" .. fn,
					{air = ambnode})
			}
		end
	end
end
allschematics.normal_garden.pos = vector.new(0, -1, 0)
allschematics.large_graveyard.pos = vector.new(0, -22, 0)
allschematics.special_final_room.pos = vector.new(0, -36, 0)
allschematics.special_final_room_2.pos = vector.new(0, -36, 0)

allschematics.large_forrest_maze.daytime = 0.5
allschematics.large_graveyard.daytime = 0.79
allschematics.large_lake.daytime = 0.5
allschematics.large_tower.daytime = 0.79
allschematics.normal_garden.daytime = 0.5
allschematics.normal_observatory.daytime = 0
allschematics.special_final_room.daytime = 0.3
allschematics.special_final_room_2.daytime = 0.3

allschematics.special_blocked.disallow_changes = true
allschematics.outside.disallow_changes = true
allschematics.outside_ruined.disallow_changes = true

do
	local depth = 36
	local height = 28
	local void = {name = modname .. ":void", force_place = true}
	local air = {name = "air", force_place = true}
	for _, xz in ipairs({20, 40}) do
		local data = {}
		for _ = 1, xz do
			for y = 1, depth + height do
				for _ = 1, xz do
					data[#data + 1] = (y > depth) and air or void
				end
			end
		end
		allschematics["clear_" .. xz] = {
			pos = vector.new(0, -depth, 0),
			mts = minetest.register_schematic({
					size = vector.new(xz, depth + height, xz),
					data = data
			})}
	end
end

-- N.B. There is a missing tree in the "outside ruined" ending area that allows
-- a player to see the old mansion below, and jump out and back into the map.
-- This should be fixed in the schematic, eventually, but for now, just hack in
-- a fix around it.
local raw_set_node = minetest.set_node
local function hotfix_helper(pos, room, ...)
	if room == allschematics.outside_ruined then
		local rel = posrel(pos)
		raw_set_node(rel(0, 1, 37), {name = "piredo_terrain:default__tree"})
		raw_set_node(rel(0, 2, 37), {name = "piredo_terrain:default__tree"})
	end
	return ...
end

function api.putschem(pos, room)
	room = allschematics[room] or error(string_format("room %q not found", room))
	if room.pos then pos = vector.add(pos, room.pos) end
	return hotfix_helper(pos, room, minetest.place_schematic(pos, room.mts))
end

function api.find_schematics(prefix)
	local t = {}
	for k in pairs(allschematics) do
		if startswith(k, prefix) then
			t[#t + 1] = k
		end
	end
	return t
end
