require('mysqloo')
local HOST = ""
local USER = ""
local PASS = ""
local PORT = 3306

Sleek = Sleek or {}
local queue = {}
Sleek.MySQL = mysqloo.connect(HOST, USER, PASS, NAME, PORT)
Sleek.MySQL.Status = Sleek.MySQL.Status or mysqloo.DATABASE_NOT_CONNECTED
Sleek.MySQL.onConnected = function()
	PrintTable(queue)
	for k, v in pairs( queue ) do
		timer.Simple(k, function()
			Sleek.MySQL:DoQuery( v[1], v[2] )
		end)
	end
	queue = {}
	Sleek.MySQL.Status = mysqloo.DATABASE_CONNECTED
	MsgN("[SleekSQLManager] Successfully to connect to database.")
	hook.Call("SleekSQLonConnected")
end
Sleek.MySQL.onConnectionFailed = function(db, err)
	MsgN("[SleekSQLManager] Failed to connect to database -> " .. err)
	Sleek.MySQL.Status = mysqloo.DATABASE_NOT_CONNECTED
end

function Sleek.MySQL.Connect()
	if !mysqloo then MsgN("[SleekSQLManager] -> Failed to load mysqloo module.\n\tPlease recheck your version to make sure it's installed correctly.\n\tAlso check to see if you have the right version.") return end
	MsgN("[SleekSQLManager] Attempting to connect to database.")
	Sleek.MySQL.Status = mysqloo.DATABASE_CONNECTING
	Sleek.MySQL:connect()
end
if Sleek.MySQL.Status == mysqloo.DATABASE_NOT_CONNECTED then
	Sleek.MySQL.Connect()
else
	MsgN("[SleekSQLManager] Already connected to database!")
end

function Sleek.MySQL:DoQuery(query, func, err)
	if !mysqloo then MsgN("[SleekSQLManager] -> Failed to load mysqloo module.\n\tPlease recheck your version to make sure it's installed correctly.\n\tAlso check to see if you have the right version.") return end
	if string.GetChar(query, query:len()) != ";" then query = query .. ";" end
	
	if Sleek.MySQL.Status == mysqloo.DATABASE_CONNECTING then
		for k,v in pairs(queue) do
			if v[1] == query then
				print("not adding duplicate to sql queue")
				return
			end
		end
		table.insert( queue, { query, func } )
		return
	end
	
	local query1 = Sleek.MySQL:query(query)
	if not query1 then
		MsgN("[SleekSQLManager] Query Failure: Unable to connect!")
		if Sleek.MySQL:status() == mysqloo.DATABASE_NOT_CONNECTED then
			for k,v in pairs(queue) do
				if v[1] == query then
					print("not adding duplicate to sql queue")
					Sleek.MySQL.Status = mysqloo.DATABASE_NOT_CONNECTED
					Sleek.MySQL.Connect()
					return
				end
			end
			table.insert( queue, { query, func } )
			Sleek.MySQL.Status = mysqloo.DATABASE_NOT_CONNECTED
			Sleek.MySQL.Connect()
			return
		end
		
		file.Append("query_failure.txt", query .. "\t" .. e .. "\n")
		
		if err then
			err(query, "Unable to connect!")
		end
	end
	query1.onAborted = function( q )
		MsgN("[SleekSQLManager] Query Aborted:", q)
		file.Append("query_aborted.txt", q .. "\n")
	end
	query1.onError = function( q, e, s )
		MsgN("[SleekSQLManager] Query Failure:", e)
		if Sleek.MySQL:status() == mysqloo.DATABASE_NOT_CONNECTED then
			for k,v in pairs(queue) do
				if v[1]  == query then
					print("not adding duplicate to sql queue")
					Sleek.MySQL.Status = mysqloo.DATABASE_NOT_CONNECTED
					Sleek.MySQL.Connect()
					return
				end
			end
			table.insert( queue, { query, func } )
			Sleek.MySQL.Status = mysqloo.DATABASE_NOT_CONNECTED
			Sleek.MySQL.Connect()
			return
		end
		
		file.Append("query_failure.txt", s .. "\t" .. e .. "\n")
		
		if err then
			err(q, e)
		end
	end
	query1.onSuccess = function(q)
		if func then
			func(q:getData())
		end
	end
	
	query1:start()
end


Sleek = Sleek or {}
Sleek.GagMutes = Sleek.GagMutes or {}
Sleek.Mutes = Sleek.Mutes or {}
Sleek.Gags = Sleek.Gags or {}

function MakeTable(ply, cmd, args)
	if IsValid(ply) then return end
	Sleek.MySQL:DoQuery("CREATE TABLE IF NOT EXISTS `gags` ( `steamid` varchar(32), `admin` text, `ungag` int(11) DEFAULT NULL, `time` int(11) DEFAULT NULL, `name` text, PRIMARY KEY (`steamid`));",
	function() end,
	function( q, e )
		MsgN("[GagMutes] -> Sync -> Failed to create gags table.\n\tReason: " .. q .. ".\n\tQuery: " .. e .. ".")
	end)
	Sleek.MySQL:DoQuery("CREATE TABLE IF NOT EXISTS `mutes` ( `steamid` varchar(32), `admin` text, `unmute` int(11) DEFAULT NULL, `time` int(11) DEFAULT NULL, `name` text, PRIMARY KEY (`steamid`));",
	function() end,
	function( q, e )
		MsgN("[GagMutes] -> Sync -> Failed to create mutes table.\n\tReason: " .. q .. ".\n\tQuery: " .. e .. ".")
	end)
end
concommand.Add("gagmutes_make", MakeTable)

function Sleek.GagMutes.Update()
	Sleek.MySQL:DoQuery( "DELETE FROM `mutes` WHERE `unmute` < UNIX_TIMESTAMP( NOW() ) " )
	Sleek.MySQL:DoQuery( "DELETE FROM `gags` WHERE `ungag` < UNIX_TIMESTAMP( NOW() ) " )
	
	Sleek.MySQL:DoQuery( "SELECT * FROM `mutes`" ,
		function( data )
			Sleek.Mutes = {}
			for k, v in pairs(data) do
				Sleek.Mutes[v['steamid']] = { admin = v['admin'], unmute = tonumber(v['unmute']), time = tonumber(v['time']), name = v['name'] }
			end
		end
	)
	
	Sleek.MySQL:DoQuery( "SELECT * FROM `gags`" ,
		function( data )
			Sleek.Gags = {}
			for k, v in pairs(data) do
				Sleek.Gags[v['steamid']] = { admin = v['admin'], ungag = tonumber(v['ungag']), time = tonumber(v['time']), name = v['name'] }
			end
		end
	)
end

hook.Add("SleekSQLonConnected", "GagMutes_onConnected", function()
	Sleek.GagMutes.Update()
end)
timer.Create("refreshGagMutes", 180, 0, function()
	Sleek.GagMutes.Update()
end)


hook.Add( "PlayerInitialSpawn", "mutegagcheck", function( ply )
	if Sleek.Gags[ply:SteamID()] and Sleek.Gags[ply:SteamID()].ungag and Sleek.Gags[ply:SteamID()].ungag > os.time() then
		local gag = Sleek.Gags[ply:SteamID()]
		local gtime = gag.ungag - os.time()
		RunConsoleCommand( "ulx", "asay", ply:Name() .. " has joined back with a " .. math.Round( gtime / 60 ) .. " min gag!" )
		RunConsoleCommand( "ulx", "psay", ply:Name(), "You had left the server with a ".. math.Round( gtime / 60 ) .." minute gag! The gag has been reapplied!" )
		ply.gag = gag.ungag
	end
	
	if Sleek.Mutes[ply:SteamID()] and Sleek.Mutes[ply:SteamID()].unmute and Sleek.Mutes[ply:SteamID()].unmute > os.time() then
		local mute = Sleek.Mutes[ply:SteamID()]
		local mtime = mute.unmute - os.time()
		RunConsoleCommand( "ulx", "asay", ply:Name() .. " has joined back with a " .. math.Round( mtime / 60 ) .. " min mute!" )
		RunConsoleCommand( "ulx", "psay", ply:Name(), "You had left the server with a ".. math.Round( mtime / 60 ) .." minute mute! The mute has been reapplied!" )
		ply.mute = mute.unmute
	end
end )


------------------------------ Mute ------------------------------
function ulx.mute( calling_ply, target_ply, time, should_unmute )
	if not should_unmute then
		if time > math.ceil( (2147483647 - os.time())/60 ) then
			ULib.tsayError( calling_ply, "A mute expiring past 03:14:07 on January 19, 2038 isn't possible!" )
			return
		end
		if target_ply.mute then
			if target_ply.mute > os.time() then
				ULib.tsayError("User already muted!", calling_ply)
				return
			else
				target_ply.mute = nil
			end
		end
		Sleek.MySQL:DoQuery( "DELETE FROM `mutes` WHERE `steamid` = '"..Sleek.MySQL:escape(target_ply:SteamID()).."'" )
		local name = target_ply:Nick()
		local steamid = target_ply:SteamID()
		local admin
		if IsValid(calling_ply) then
			admin = calling_ply:Nick().."("..calling_ply:SteamID()..")"
		else
			admin = "(CONSOLE)"
		end
		local mtime = os.time() + time * 60
		Sleek.MySQL:DoQuery("INSERT INTO `mutes` (`steamid`, `admin`, `unmute`, `time`, `name`) VALUES('" .. Sleek.MySQL:escape(steamid) .. "', '" .. Sleek.MySQL:escape(admin) .. "', '" .. mtime .. "', UNIX_TIMESTAMP(), '" .. Sleek.MySQL:escape(name) .. "')")
		Sleek.Mutes[steamid] = { admin = admin, unmute = mtime, time = os.time(), name = name}
		target_ply.mute = mtime
		if time == 1 then
			ulx.fancyLogAdmin( calling_ply, "#A muted #T for a minute", target_ply ) --more swag
		else
			ulx.fancyLogAdmin( calling_ply, "#A muted #T for #i minutes", target_ply, time )
		end
	elseif should_unmute then
		target_ply.mute = nil
		Sleek.MySQL:DoQuery( "DELETE FROM `mutes` WHERE `steamid` = '"..Sleek.MySQL:escape(target_ply:SteamID()).."'" )
		ulx.fancyLogAdmin( calling_ply, "#A unmuted #T", target_ply )
	end
end
local mute = ulx.command( "Chat", "ulx mute", ulx.mute, "!mute" )
mute:addParam{ type=ULib.cmds.PlayerArg }
mute:addParam{ type=ULib.cmds.NumArg, hint="length of mute", ULib.cmds.allowTimeString, min=0 }
mute:addParam{ type=ULib.cmds.BoolArg, invisible=true }
mute:help( "Mutes target for x minutes." )
mute:setOpposite( "ulx unmute", {_, _, 0, true}, "!unmute" )
 
 
------------------------------ Gag ------------------------------
function ulx.gag( calling_ply, target_ply, time, should_ungag )

	if not should_ungag then
		if time > math.ceil( (2147483647 - os.time())/60 ) then
			ULib.tsayError( calling_ply, "A gag expiring past 03:14:07 on January 19, 2038 isn't possible!" )
			return
		end
		if target_ply.gag then
			if target_ply.gag > os.time() then
				ULib.tsayError("User already gagged!", calling_ply)
				return
			else
				target_ply.gag = nil
			end
		end
		Sleek.MySQL:DoQuery( "DELETE FROM `gags` WHERE `steamid` = '"..Sleek.MySQL:escape(target_ply:SteamID()).."'" )
		local name = target_ply:Nick()
		local steamid = target_ply:SteamID()
		local admin
		if IsValid(calling_ply) then
			admin = calling_ply:Nick().."("..calling_ply:SteamID()..")"
		else
			admin = "(CONSOLE)"
		end
		local gtime = os.time() + time * 60
		Sleek.MySQL:DoQuery("INSERT INTO `gags` (`steamid`, `admin`, `ungag`, `time`, `name`) VALUES('" .. Sleek.MySQL:escape(steamid) .. "', '" .. Sleek.MySQL:escape(admin) .. "', '" .. gtime .. "', UNIX_TIMESTAMP(), '" .. Sleek.MySQL:escape(name) .. "')")
		Sleek.Gags[steamid] = { admin = admin, ungag = gtime, time = os.time(), name = name}
		target_ply.gag = gtime
		
		if time == 1 then
			ulx.fancyLogAdmin( calling_ply, "#A gagged #T for a minute", target_ply )
		else
			ulx.fancyLogAdmin( calling_ply, "#A gagged #T for #i minutes", target_ply, time )
		end
	else
		target_ply.gag = nil
		Sleek.MySQL:DoQuery( "DELETE FROM `gags` WHERE `steamid` = '"..Sleek.MySQL:escape(target_ply:SteamID()).."'" )
		ulx.fancyLogAdmin( calling_ply, "#A ungagged #T", target_ply )
	end
end
local gag = ulx.command( "Chat", "ulx gag", ulx.gag, "!gag" )
gag:addParam{ type=ULib.cmds.PlayerArg }
gag:addParam{ type=ULib.cmds.NumArg, hint="length of gag", ULib.cmds.allowTimeString, min=0 }
gag:addParam{ type=ULib.cmds.BoolArg, invisible=true }
gag:help( "Gag target for x minutes." )
gag:setOpposite( "ulx ungag", {_, _, 0, true}, "!ungag" )

-- Remove nasty ULX hooks that don't do anything now.
hook.Remove("PlayerCanHearPlayersVoice", "ULXGag")
hook.Remove("PlayerSay", "ULXGimpCheck")

function ulx.asay( calling_ply, message )
	if calling_ply.mute then
		if calling_ply.mute > os.time() then
			return
		elseif calling_ply.mute < os.time() then
			ply.mute = nil
		end
	end
	
	local format = "#P to admins: #s"


	local players = player.GetAll()
	for i=#players, 1, -1 do
		local v = players[ i ]
		if not ULib.ucl.query( v, "ulx seeasay" ) and v ~= calling_ply then -- Calling player always gets to see the echo
			table.remove( players, i )
		end
	end
	ulx.fancyLog( players, format, calling_ply, message )
end
local asay = ulx.command( CATEGORY_NAME, "ulx asay", ulx.asay, "@", true, true )
asay:addParam{ type=ULib.cmds.StringArg, hint="message", ULib.cmds.takeRestOfLine }
asay:defaultAccess( ULib.ACCESS_ALL )
asay:help( "Send a message to currently connected admins." )

hook.Add("PlayerSay", "KeepMutedPeopleQuiet", function(ply)
	if ply.mute then
		if ply.mute > os.time() then
			return ""
		elseif ply.mute < os.time() then
			ply.mute = nil
		end
	end
end,-1) --HOOK_HIGH makes this get called before normal scripts