ulx.rulesLink = "https://rules-mrp.modern-gaming.net/docs/rules/"

function ulx.respawn(calling_ply, target_plys)
	local affected_plys = {}
	for i=1, #target_plys do
		local v = target_plys[i]
		table.insert(affected_plys, v)
		v:Spawn()
	end
	ulx.fancyLogAdmin(calling_ply, "#A respawned #T", affected_plys)
end
local respawn = ulx.command("Utility", "ulx respawn", ulx.respawn, "!respawn")
respawn:addParam{type=ULib.cmds.PlayersArg, ULib.cmds.optional}
respawn:defaultAccess(ULib.ACCESS_ADMIN)
respawn:help("Respawn target(s).")

function ulx.cleardecals(calling_ply)
	for _,v in ipairs(player.GetAll()) do
		v:ConCommand("r_cleardecals")
	end
	ulx.fancyLogAdmin(calling_ply, "#A cleared decals.")
end
local cleardecals = ulx.command("Utility", "ulx cleardecals", ulx.cleardecals, "!cleardecals")
cleardecals:defaultAccess(ULib.ACCESS_ADMIN)
cleardecals:help("Clears decals.\nNote: This does not fix lag.")

function ulx.stopsound(calling_ply)
	for _,v in ipairs(player.GetAll()) do
		v:ConCommand("stopsound")
	end
	ulx.fancyLogAdmin(calling_ply, "#A ran stopsound on all players.")
end
local stopsound = ulx.command("Utility", "ulx stopsound", ulx.stopsound, "!stopsound")
stopsound:defaultAccess(ULib.ACCESS_ADMIN)
stopsound:help("Stops all sounds.\nNote: This does not fix lag.")

function ulx.freezeprops(calling_ply)
	for _,v in ipairs(ents.FindByClass("prop_physics")) do
		local phys = v:GetPhysicsObject()
		if !IsValid(phys) then continue end
		phys:EnableMotion(false)
	end
	ulx.fancyLogAdmin(calling_ply, "#A freezed all props.")
end
local freezeprops = ulx.command("Utility", "ulx freezeprops", ulx.freezeprops, "!freezeprops")
freezeprops:defaultAccess(ULib.ACCESS_ADMIN)
freezeprops:help("Freeze all props on the map.\nNote: This actually does fix serverlag introduced by props.")

if SERVER then
	util.AddNetworkString("openrulepage")
	util.AddNetworkString("closerulepage")
end

if CLIENT then
	net.Receive("openrulepage", function()
		local time = net.ReadFloat(32)
		ulx.openrulespanel(time)
	end)

	local rulepanel
	net.Receive("closerulepage", function()
		if IsValid(rulepanel) then
			rulepanel:Remove()
		end
	end)

	function ulx.openrulespanel(time)
		if IsValid(rulepanel) then rulepanel:Remove() return end
		rulepanel = vgui.Create("DFrame")
		rulepanel:SetSize(ScrW() * 0.95, ScrH() * 0.95)
		rulepanel:Center()
		rulepanel:SetVisible(true)
		rulepanel:SetDraggable(false)
		rulepanel:ShowCloseButton(false)
		rulepanel:SetKeyboardInputEnabled(false)
		rulepanel:SetTitle("Bitte lese dir unsere Regeln erneut durch, um dein Regelverständnis aufzufrischen. Diese Seite verschwindet in "..string.ToMinutesSeconds(time - CurTime()).." min automatisch.")
		rulepanel:MakePopup()
		rulepanel.Think = function()
			rulepanel:SetTitle("Bitte lese dir unsere Regeln erneut durch, um dein Regelverständnis aufzufrischen. Diese Seite verschwindet in "..string.ToMinutesSeconds(time - CurTime()).." min automatisch.")
			if time - CurTime() <= 0 then
				rulepanel:Close()
			end
		end
		local page = vgui.Create("HTML", rulepanel)
		page:SetPos(10, 30)
		page:SetSize(rulepanel:GetWide() - 20, rulepanel:GetTall() - 40)
		page:OpenURL(ulx.rulesLink)
	end
end

function ulx.openrules(calling_ply, target_ply, length)
	net.Start("openrulepage")
		net.WriteFloat(CurTime() + length + 1, 32)
	net.Send(target_ply)
	ulx.fancyLogAdmin(calling_ply, "#A opened the rules for #T for #i seconds", target_ply, length)
end
local openrules = ulx.command("Utility", "ulx openrules", ulx.openrules, "!openrules")
openrules:addParam{type=ULib.cmds.PlayerArg}
openrules:addParam{type=ULib.cmds.NumArg, min=60, max=600, default=300, hint="length", ULib.cmds.round}
openrules:defaultAccess(ULib.ACCESS_ADMIN)
openrules:help("Opens a un-closable rules page for target.")

function ulx.closerules(calling_ply, target_plys)
	local affected_plys = {}
	for i=1, #target_plys do
		local v = target_plys[i]
		net.Start("closerulepage")
		net.Send(v)
		table.insert(affected_plys, v)
	end
	ulx.fancyLogAdmin(calling_ply, "#A closed the rules of #T", affected_plys)
end
local closerules = ulx.command("Utility", "ulx closerules", ulx.closerules, "!closerules")
closerules:addParam{type=ULib.cmds.PlayersArg}
closerules:defaultAccess(ULib.ACCESS_ADMIN)
closerules:help("Closes the rules page of target(s) early.")

function ulx.reconnect(calling_ply, target_ply)
	target_ply:SendLua([[RunConsoleCommand("retry")]])
	ulx.fancyLogAdmin(calling_ply, "#A reconnected #T", target_ply)
end
local reconnect = ulx.command("Utility", "ulx reconnect", ulx.reconnect, "!reconnect")
reconnect:addParam{type=ULib.cmds.PlayerArg}
reconnect:defaultAccess(ULib.ACCESS_ADMIN)
reconnect:help("Reconnects target.")

local c_weps = {
	["weapon_crowbar"] = true,
	["weapon_stunstick"] = true,
	["weapon_physcannon"] = true,
	["weapon_physgun"] = true,
	["weapon_pistol"] = true,
	["weapon_357"] = true,
	["weapon_smg1"] = true,
	["weapon_ar2"] = true,
	["weapon_ar2"] = true,
	["weapon_shotgun"] = true,
	["weapon_crossbow"] = true,
	["weapon_slam"] = true,
	["weapon_rpg"] = true,
	["weapon_bugbait"] = true
}
function ulx.give(calling_ply, target_plys, weapon)
	if (c_weps[weapon] != true and !weapons.Get(weapon)) then ULib.tsayError(calling_ply, "This isn't a valid classname!") return end
	local affected_plys = {}
	for i=1, #target_plys do
		local v = target_plys[i]
		table.insert(affected_plys, v)
		v:Give(weapon)
		v:SelectWeapon(weapon)
	end
	ulx.fancyLogAdmin(calling_ply, "#A gave #s to #T", weapon, affected_plys)
end
local give = ulx.command("Utility", "ulx give", ulx.give, "!give")
give:addParam{type=ULib.cmds.PlayersArg}
give:addParam{type=ULib.cmds.StringArg, hint="classname",  ULib.cmds.takeRestOfLine}
give:defaultAccess(ULib.ACCESS_ADMIN)
give:help("Give weapon to target(s).")

function ulx.resetscore(calling_ply, target_plys)
	local affected_plys = {}
	for i=1, #target_plys do
		local v = target_plys[i]
		table.insert(affected_plys, v)
		v:SetFrags(0)
		v:SetDeaths(0)
	end
	ulx.fancyLogAdmin(calling_ply, "#A reset the score of #T", affected_plys)
end
local resetscore = ulx.command("Utility", "ulx resetscore", ulx.resetscore, "!reset")
resetscore:addParam{type=ULib.cmds.PlayersArg}
resetscore:defaultAccess(ULib.ACCESS_ADMIN)
resetscore:help("Reset kills and deaths of target(s).")

local hook_name = "ULX_Invis"
local invis_tbl = {}
function ulx.invis_think()
	for i=#invis_tbl, 1, -1 do
		local ply = invis_tbl[i]
		if !IsValid(ply) or !ply:GetNoDraw() or ply:IsSolid() then
			table.remove(invis_tbl, i)
			if #invis_tbl == 0 then
				hook.Remove("Think", hook_name)
				return
			end
			continue
		end
		local wep = ply:GetActiveWeapon()
		if wep:IsValid() then
			wep:SetNoDraw(true)
		end
	end
end

function ulx.invis_leave(ply)
	if table.HasValue(invis_tbl, ply) then
		table.remove(invis_tbl, i)
		if #invis_tbl == 0 then
			hook.Remove("Think", hook_name)
		end
		ply:SetNoDraw(false)
		ply:SetNotSolid(false)
		for _, v in ipairs(ply:GetWeapons()) do
			v:SetNoDraw(false)
		end
	end
end

function ulx.invis(calling_ply, target_plys, bool)
	if !target_plys[1]:IsValid() then
		Msg("You are always invisible.\n")
		return
	end
	local affected_plys = {}
	for i=1, #target_plys do
		local ply = target_plys[i]
		if !ply:Alive() then
			ULib.tsayError(calling_ply, ply:Name().." is dead!")
			continue
		end
		local invis = ply:GetNoDraw() and !ply:IsSolid()
		if (bool and !invis) or (!bool and invis) then
			ULib.tsayError(calling_ply, ply:Name().." is already "..(bool and "visible" or "invisible").."!")
			continue
		end
		table.insert(affected_plys, ply)
		ply:SetNoDraw(!bool)
		ply:SetNotSolid(!bool)
		for _, v in ipairs(ply:GetWeapons()) do
			v:SetNoDraw(true)
		end
		if !bool then
			if #invis_tbl == 0 then
				hook.Add("Think", hook_name, ulx.invis_think)
				hook.Add("PlayerLeaveVehicle", hook_name, ulx.invis_leave)
			end
			table.insert(invis_tbl, ply)
			hook.Run("ULX_Invis", ply, true)
		else
			for _, v in ipairs(ply:GetWeapons()) do
				v:SetNoDraw(false)
			end
			table.RemoveByValue(invis_tbl, ply)
			if #invis_tbl == 0 then
				hook.Remove("Think", hook_name)
				hook.Remove("PlayerLeaveVehicle", hook_name, ulx.invis_leave)
			end
			hook.Run("ULX_Invis", ply, false)
		end
	end
	ulx.fancyLogAdmin(calling_ply, true, "#A set #T "..(bool and "visible" or "invisible"), affected_plys)
end
local invis = ulx.command("Utility", "ulx invis", ulx.invis, "!invis")
invis:addParam{type=ULib.cmds.PlayersArg, ULib.cmds.optional}
invis:addParam{type=ULib.cmds.BoolArg, invisible=true}
invis:defaultAccess(ULib.ACCESS_ADMIN)
invis:help("Makes target(s) invisible.")
invis:setOpposite("ulx vis", {_, _, true}, "!vis")

function ulx.imitate(calling_ply, target_plys, text)
	for i=1, #target_plys do
		target_plys[i]:ConCommand("say "..text)
	end
	ulx.fancyLogAdmin(calling_ply, true, "#A made #T say #s", target_plys, text)
end
local imitate = ulx.command("Chat", "ulx imitate", ulx.imitate, "!imitate")
imitate:addParam{type=ULib.cmds.PlayersArg}
imitate:help("Makes target(s) say something.")
imitate:defaultAccess(ULib.ACCESS_SUPERADMIN)
imitate:addParam{type=ULib.cmds.StringArg, hint="text", ULib.cmds.takeRestOfLine}

function ulx.hide(calling_ply, bool)
	calling_ply:SetMGVar("scoreboard_hide", !bool)
	ulx.fancyLogAdmin(calling_ply, true, "#A "..(!bool and "hid themselves in scoreboard" or "made themselves appear in scoreboard again"), target_plys, text)
end
local hide = ulx.command("Utility", "ulx hide", ulx.hide, "!hide")
hide:addParam{type=ULib.cmds.BoolArg, invisible=true}
hide:help("Hides yourself in scoreboard.")
hide:defaultAccess(ULib.ACCESS_SUPERADMIN)
hide:setOpposite("ulx unhide", {_, true}, "!unhide")