local tournament_starting_time = tonumber(minetest.settings:get("pvpplus.tournament_starting_time")) or 60 -- seconds
local tournament = pvpplus.tournament -- Shortcut reference

minetest.register_privilege("tournament_mod", "PvP Tournament Moderator")

local function check_permission(name)
	if minetest.get_player_privs(name).tournament_mod then
		return true
	end
	if (tournament.starting_infos.starter or "") == name then
		return true
	end
	return false
end

minetest.register_chatcommand("start_global_tournament", {
	params = "",
	description = "Start a PvP tournament engaging every connected players and starting immediately",
	privs = {interact = true, tournament_mod = true},
	func = function(name, param)
		-- Fill start infos
		tournament.starting_infos.starter = name
		tournament.starting_infos.open_time = nil
		tournament.starting_infos.start_time = os.time()

		return pvpplus.start_global_tournament(name)
	end
})

minetest.register_chatcommand("stop_tournament", {
	params = "",
	description = "Stops the current PvP tournament",
	privs = {interact = true},
	func = function(name, param)
		if not pvpplus.is_running_tournament() then
			return false, "There is no currently running tournament."
		end
		if not check_permission(name) then
			return false, "You have no permission to stop this tournament."
		end
		pvpplus.stop_tournament()
		return true
	end
})

minetest.register_chatcommand("remove_from_tournament", {
	params = "<name>",
	description = "Removes a player from a PvP tournament",
	privs = {interact = true},
	func = function(name, param)
		if not pvpplus.is_playing_tournament(name) then
			return false, "Player " .. name .. " is not currently playing a tournament."
		end
		if not check_permission(name) then
			return false, "You have no permission to remove a player from this tournament."
		end
		if not minetest.get_player_by_name(param) then
			return false, "Player does not exist. Please refer to usage: /help remove_from_tournament"
		end
		minetest.chat_send_player(param, "You have been removed from the tournament by " .. name)
		pvpplus.remove_from_tournament(param)
	end
})

minetest.register_chatcommand("add_to_tournament", {
	params = "<name>",
	description = "Adds a player to the current tournament",
	privs = {interact = true, tournament_mod = true},
	func = function(name, param)
		if not minetest.get_player_by_name(param) then
			return false, "Player does not exist. Please refer to usage: /help add_from_tournament"
		end
		if pvpplus.is_playing_tournament(player) then
			return false, "Player is already playing a tournament."
		end
		if not pvpplus.is_running_tournament() then
			return false, "There is no currently running tournament."
		end
		minetest.chat_send_player(param, "You have been added to the current tournament by " .. name)
		pvpplus.add_to_tournament(param)
	end
})

minetest.register_chatcommand("leave_tournament", {
	params = "",
	description = "Leaves a PvP tournament",
	privs = {interact = true},
	func = function(name, param)
		if not pvpplus.is_playing_tournament(name) then
			return false, "You are not playing a tournament."
		end
		pvpplus.remove_from_tournament(name)
	end
})

minetest.register_chatcommand("engage", {
	params = "",
	description = "Engages for the next PvP tournament",
	privs = {interact = true},
	func = function(name, param)
		if pvpplus.is_playing_tournament(name) then
			return false, "You are already playing a tournament."
		end
		if not pvpplus.is_engaging_players() then
			return false, "There is no opened tournament. Type /tournament!"
		end
		pvpplus.engage_player(name)
		minetest.chat_send_all("Player "..name.." engaged himself/herself for the PvP tournament!")
	end
})

minetest.register_chatcommand("tournament_info", {
	params = "",
	description = "Prints tournament informations",
	privs = {},
	func = function(name, param)
		if pvpplus.is_engaging_players() then
			local str = "There is an open tournament which is not yet started (you can engage for this tournament by typing /engage).\n" ..
			            "The tournament was open by: " .. tournament.starting_infos.starter ..
			            "\nThe tournament will start in: " .. os.difftime(tournament.starting_infos.start_time, os.time()) .. " seconds\n" ..
				    "The tournament is open since: " .. os.date("%c", tournament.starting_infos.open_time) ..
				    (tournament.engagement_position and "\nEngaged players will be teleported before the tournament starts.\n" or "\nEngaged players won't be teleported.\n") ..
				    (tournament.damage_motionless and "Motionless players will be automatically damaged." or "Motionless players won't be damaged.") ..
				    "\nCurrently engaged players are: "
			for player, _ in pairs(tournament.engaged_players) do
				str = str .. player .. ", "
			end
			str = str:sub(0, -3)

			return true, str
		elseif pvpplus.is_running_tournament() then
			local str = "There is a currrently running tournament.\n" ..
			            "The tournament was open by: " .. tournament.starting_infos.starter ..
			            "\nThe tournament is running since: " .. os.date("%c", tournament.starting_infos.start_time) ..
				    (tournament.damage_motionless and "\nMotionless players are automatically damaged." or "\nMotionless players are not damaged.") ..
				    "\nInitially engaged players were: "
			for player, _ in pairs(tournament.starting_infos.initially_engaged_players) do
				str = str .. player .. ", "
			end
			str = str:sub(0, -3)

			str = str .. "\nRemaining players are: "
			for player, _ in pairs(tournament.players) do
				str = str .. player .. ", "
			end
			str = str:sub(0, -3)

			return true, str
		else
			return true, "There is no currently running tournament. You can start a new tournament by using /tournament (see /help tournament)."
		end
	end
})

minetest.register_chatcommand("tournament_music_toggle", {
	params = "",
	description = "Toggles the music loop",
	privs = {},
	func = function(name, param)
		if not pvpplus.is_playing_tournament(name) then
			return false, "You are not currently playing a tournament. If you're hearing the tournament music, then it's a bug, please contact a moderator."
		end
		if tournament.sound_handles[name] then
			minetest.sound_stop(tournament.sound_handles[name])
			tournament.sound_handles[name] = nil
			return true, "Stopped music loop."
		else
			tournament.sound_handles[name] = minetest.sound_play("pvpplus_tournament_loop", {
				to_player = name,
				gain = 1.0,
				loop = true,
			})
			return true, "Started music loop."
		end
	end
})

--- /tournament command ---

-- value: {[bool: whether the parameter requires the tournament_mod privilege], [string: type of the wanted value (number or string), nil if no value]}
local param_list = {
	noteleport = {false, nil},
	start_delay = {false, "number"},
	broadcast = {true, nil},
	damage_motionless = {false, nil},
}

local function parse_params(param, name)
	local params = param:split(" ")
	local param_table = {}
	for _, param in ipairs(params) do
		local opt, val = param:match("(.+)=(.*)")
		if opt then
			param = opt
		end

		-- Validity checks...
		if not param_list[param] then
			return false, "Invalid option: " .. param
		end
		if param_list[param][1] and not minetest.get_player_privs(name).tournament_mod then
			return false, "Option " .. param .. " requires the tournament_mod privilege."
		end
		if val and not param_list[param][2] then
			return false, "Option " .. param .. " should not be used with a value."
		end
		if not val and param_list[param][2] then
			return false, "Option " .. param .. " expects a value (e.g. option=value)."
		end
		if param_list[param][2] == "number" and tonumber(val) == nil then
			return false, "Option " .. param .. " expects a number as value."
		end

		if val then
			if param_list[param][2] == "number" then
				param_table[param] = tonumber(val)
			else -- string
				param_table[param] = val
			end
		else
			param_table[param] = true
		end
	end
	return true, param_table
end

minetest.register_chatcommand("tournament", {
	params = "[noteleport] [broadcast] [start_delay=<seconds>]",
	description = "Creates a new tournament, optionally teleporting players to your current position 10 seconds before the tournament starts.",
	privs = {interact = true},
	func = function(name, param)
		local params
		do
			local ok, res = parse_params(param, name)
			if ok == false then
				return false, res
			end
			params = res
		end

		local starting_time = params.start_delay or tournament_starting_time
		if starting_time < 10 or starting_time > 600 then
			return false, "Please set a start delay between 10s and 600s."
		end
		local teleport = params.noteleport ~= true
		tournament.broadcast_messages = params.broadcast or false
		tournament.damage_motionless = params.damage_motionless or false

		-- Fill start infos
		tournament.starting_infos.starter = name
		tournament.starting_infos.open_time = os.time()
		tournament.starting_infos.start_time = os.time() + starting_time

		-- Allow engaging
		local e, m = pvpplus.allow_engaging(name, teleport)
		if e == false then
			return false, m
		end

		-- Engage starter
		pvpplus.engage_player(name)

		-- Chat messages
		local chat_send = (params.broadcast and minetest.chat_send_all) or pvpplus.chat_send_tournament
		minetest.chat_send_all("The tournament will begin in " .. tostring(starting_time).."s.") -- First chat message is always broadcasted
		minetest.after(starting_time - 10, function()
			pvpplus.chat_send_tournament("The tournament will begin in 10s! Engage yourself by typing /engage!", true)
			pvpplus.teleport_engaged_players()
		end)
		minetest.after(starting_time - 5, function()
			pvpplus.chat_send_tournament("The tournament will begin in 5s!", true)
		end)
		for i = 1, 4 do
			minetest.after(starting_time - i, function()
				pvpplus.chat_send_tournament(tostring(i).."!", true)
			end)
		end

		-- Start tournament
		minetest.after(starting_time, function(name)
			local ok, e = pvpplus.start_tournament()
			if ok == false and e then
				minetest.chat_send_player(name, e)
			end
		end, name)
	end
})
