--[[ This mod is basically a compromise solution
for a long-known bug.

It checks if Minetest is running with the recommended
player movement settings. If the player has set any of the
relevant movement settings to a non-default value, that will
take preference over the game settings, which will break
this game’s vision somewhat, since the levels are carefully
designed to work with the game-provided movement settings.

Since there apparently is no way for Glitch to force-set
the movement settings without some arcane hackery, this mod
will just check the values and display a warning if a
deviation has been detected.
(This is important because it is very hard for a player
to realize otherwise they're playing Glitch with the
"wrong" physics.)

The player is then given a choice to either return to
Minetest and fix the problem or to ignore it and
continue playing.
Both a dialog message and a chat message will be displayed.

FIXME: Find a non-hacky (!) way for Glitch to force player-movement
settings, then remove this mod.
]]

glitch_check_movement_settings = {}

-- Ignore the physics problems if in editor mode
if glitch_editor.is_active() then
	glitch_check_movement_settings.check_movement_settings = function()
		return true
	end
	return
end

local S = minetest.get_translator("glitch_check_movement_settings")

-- Threshold for floating-point equality check
local EPSILON = 0.0001

-- This is the list of settings that needed to be checked, and their
-- expected value.
-- IMPORTANT: This MUST be equal to minetest.conf in this game's root directory!
local settings_to_check = {
	movement_speed_walk = 5.8,
	movement_speed_crouch = 5.8,
	movement_speed_climb = 4.0,
	movement_speed_jump = 6.3,
	movement_gravity = 8,
	movement_acceleration_air = 0.5,
	movement_acceleration_default = 4,
}

local check_settings = function()
	local invalid_settings = {}
	for key, expected_value in pairs(settings_to_check) do
		local actual_value = tonumber(minetest.settings:get(key))
		if actual_value then
			-- Floating-point equality check with tolerance
			if math.abs(expected_value - actual_value) > EPSILON then
				table.insert(invalid_settings, key)
			end
		end
	end
	return invalid_settings
end

invalid_settings = check_settings()

local STR_WARNING_1 = S("WARNING: The player movement settings are not at the recommended values for Glitch. The physics might not work as intended!")
local STR_WARNING_2 = S("Please exit the game and reset the following Minetest settings to their default value:")
-- concatenate invalid settings with list separator (comma)
local STR_INVALID_SETTINGS = table.concat(invalid_settings, S(", "))

local disconnect = function(player)
	minetest.log("action", "[glitch_check_movement_settings] "..player:get_player_name().." chose to leave the game")
	minetest.disconnect_player(player:get_player_name(), S("You quit. Remember, Glitch expects the following Minetest settings to be reset to the default value: @1", STR_INVALID_SETTINGS))
end

glitch_dialog.register_dialogtree("glitch:non_default_movement_settings", {
	force_stay = true,
	speeches = {
		start = {
			speaker = "glitch:warning",
			text = STR_WARNING_1.."\n"..
				STR_WARNING_2.."\n"..
				STR_INVALID_SETTINGS,
			options = {
				{
					-- This will exit the game
					text = S("Exit game"),
					action = "speech",
					next_speech = "exit_game",
				},
				{
					text = S("Continue playing anyway"),
					action = "speech",
					next_speech = "play",
				}
			},
		},
		exit_game = {
			-- Fake speech that will cause an immediate disconnect when entered
			speaker = "glitch:warning",
			-- Speech text not needed here
			text = "",
			on_enter = function(player)
				disconnect(player)
			end,
		},
		play = {
			speaker = "glitch:info",
			text = S("Okay, have fun!"),
			on_exit = function(player)
				-- Move the player to the start of the game if intro was not completed yet
				local pmeta = player:get_meta()
				if pmeta:get_int("glitch_levels:intro_complete") == 0 then
					minetest.log("action", "[glitch_check_movement_settings] "..player:get_player_name().." chose to play game despite the non-default movement settings")
					if minetest.global_exists("glitch_levels") then
						glitch_levels.move_to_level(player, glitch_levels.START_LEVEL, glitch_levels.START_SPAWN_NO)
					else
						minetest.log("error", "[glitch_check_movement_settings] Could not teleport player to start level!")
					end
				end
			end,
		},

	},
})

minetest.register_on_joinplayer(function(player)
	local pname = player:get_player_name()
	if #invalid_settings == 0 then
		return
	end

	minetest.log("action", "[glitch_check_movement_settings] Non-default movement settings detected, game physics might be degraded")
	-- Chat messages
	local function msg(text)
		minetest.chat_send_player(pname, minetest.colorize("#FF8000", text))
	end
	msg(STR_WARNING_1)
	msg(STR_WARNING_2)
	msg(STR_INVALID_SETTINGS)

	-- Additional, a dialog tree
	glitch_dialog.show_dialogtree(player, "glitch:non_default_movement_settings")
end)


-- Expose checker function publicly
glitch_check_movement_settings = {}
glitch_check_movement_settings.check_movement_settings = function()
	local t = check_settings()
	if #t == 0 then
		return true
	else
		return false
	end
end

