local S = minetest.get_translator("lzr_editor")

minetest.register_chatcommand("editor", {
	privs = { server = true },
	description = S("Start or exit level editor"),
	params = S("[ enter | exit ]"),
	func = function(name, param)
		if param == "" or param == "enter" then
			local state = lzr_gamestate.get_state()
			if state == lzr_gamestate.EDITOR then
				return false, S("Already in level editor!")
			elseif state == lzr_gamestate.LEVEL or state == lzr_gamestate.LEVEL_COMPLETE then
				lzr_gamestate.set_state(lzr_gamestate.EDITOR)
				return true
			else
				lzr_levels.start_level(1)
				lzr_gamestate.set_state(lzr_gamestate.EDITOR)
				return true
			end
		elseif param == "exit" then
			local state = lzr_gamestate.get_state()
			if state ~= lzr_gamestate.EDITOR then
				return false, S("Not in level editor!")
			else
				lzr_gamestate.set_state(lzr_gamestate.LEVEL)
				return true
			end
		end
		return false
	end,
})

minetest.register_chatcommand("editor_size", {
	privs = { server = true },
	description = S("Set level size for editor (warning: clears level contents!)"),
	params = "<x>,<y>,<z>",
	func = function(name, param)
		if lzr_gamestate.get_state() ~= lzr_gamestate.EDITOR then
			return false, S("Not in editor mode!")
		end
		local size = minetest.string_to_pos(param)
		if not size then
			return false
		end
		if size.x > lzr_globals.PLAYFIELD_SIZE.x-1 or
				size.y > lzr_globals.PLAYFIELD_SIZE.y-1 or
				size.z > lzr_globals.PLAYFIELD_SIZE.z-1 then
			return false, S("Too large!")
		end
		if size.x < 1 or size.y < 4 or size.z < 1 then
			return false, S("Too small!")
		end
		lzr_levels.clear_playfield(size)
		lzr_levels.build_room({pos=lzr_globals.LEVEL_POS, size=size})
		return true
	end,
})

-- Dummy save and load functions (only 1 level name supported for now)
minetest.register_chatcommand("editor_save", {
	privs = { server = true },
	description = S("Save current level"),
	params = "",
	func = function(name, param)
		-- TODO: Don't save the lasers
		if lzr_gamestate.get_state() ~= lzr_gamestate.EDITOR then
			return false, S("Not in editor mode!")
		end
		local num = tonumber(param)
		if not num then
			num = 1
		end
		num = math.max(1, math.floor(num))
		local level_name = "level_custom_"..num
		minetest.mkdir(minetest.get_worldpath().."/levels")
		local filename = minetest.get_worldpath().."/levels/"..level_name..".mts"
		local size = vector.subtract(lzr_levels.get_level_size(), vector.new(1, 1, 1))
		local ok = minetest.create_schematic(lzr_globals.LEVEL_POS, vector.add(lzr_globals.LEVEL_POS, size), {}, filename, {})
		if ok then
			minetest.log("action", "[lzr_editor] Level written to "..filename)
			return true, S("Level saved to @1.", filename)
		else
			minetest.log("error", "[lzr_editor] Failed to write level to "..filename)
			return false, S("Error writing level file!")
		end
	end,
})

-- Returns true if the given file exists, false otherwise.
-- * path: Path to file (without file name)
-- * filename: File name of file (without path)
local file_exists = function(path, filename)
	local levels = minetest.get_dir_list(path, false)
	for l=1, #levels do
		if levels[l] == filename then
			return true
		end
	end
	return false
end

minetest.register_chatcommand("editor_load", {
	privs = { server = true },
	description = S("Load level"),
	params = "",
	func = function(name, param)
		if lzr_gamestate.get_state() ~= lzr_gamestate.EDITOR then
			return false, S("Not in editor mode!")
		end
		local num = tonumber(param)
		if not num then
			num = 1
		end
		num = math.max(1, math.floor(num))
		local level_name = "level_custom_"..num
		local ok = file_exists(minetest.get_worldpath().."/levels", level_name..".mts")
		if not ok then
			return false, S("Level file does not exist!")
		end
		local filename = minetest.get_worldpath().."/levels/"..level_name..".mts"
		local schem = minetest.read_schematic(filename, {write_yslice_prob="none"})
		if schem then
			lzr_levels.prepare_and_build_custom_level(schem)
			minetest.log("action", "[lzr_editor] Level loaded from "..filename)
			return true, S("Level loaded.")
		else
			minetest.log("error", "[lzr_editor] Failed to read level from "..filename)
			return false, S("Error reading level file!")
		end
	end,
})

-- Unlimited node placement in editor mode
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)
	if placer and placer:is_player() then
		return lzr_gamestate.get_state() == lzr_gamestate.EDITOR
	end
end)

-- Don't pick node up if the item is already in the inventory
local old_handle_node_drops = minetest.handle_node_drops
function minetest.handle_node_drops(pos, drops, digger)
	if not digger or not digger:is_player() or
		lzr_gamestate.get_state() ~= lzr_gamestate.EDITOR then
		return old_handle_node_drops(pos, drops, digger)
	end
	local inv = digger:get_inventory()
	if inv then
		for _, item in ipairs(drops) do
			if not inv:contains_item("main", item, true) then
				inv:add_item("main", item)
			end
		end
	end
end

lzr_gamestate.register_on_enter_state(function(state)
	if state == lzr_gamestate.EDITOR then
		local player = minetest.get_player_by_name("singleplayer")
		lzr_player.set_editor_inventory(player)
		lzr_gui.set_editor_gui(player)
		lzr_ambience.set_ambience("none")
	end
end)
