do
	local passiveTimerGroups = {}
	local cleanUpInterval = 240000
	local nextCleanUpCycle = getTickCount() + cleanUpInterval
	
	local onElementDestroyEventName = triggerServerEvent and "onClientElementDestroy" or "onElementDestroy"
	
	local function isEventHandlerAdded( eventName, elementAttachedTo, func ) -- https://wiki.multitheftauto.com/wiki/GetEventHandlers
		local attachedFunctions = getEventHandlers( eventName, elementAttachedTo )
		if #attachedFunctions > 0 then
			for i=1, #attachedFunctions do
				if attachedFunctions[i] == func then
					return true
				end
			end
		end
		return false
	end
	--[[
		Remove passive timers of elements that are destroyed
	]]
	local function removeDeletedElementTimer ()
		for timerName, passiveTimers in pairs(passiveTimerGroups) do
			if passiveTimers[this] then
				passiveTimers[this] = nil
				if not next(passiveTimers) then
					passiveTimerGroups[timerName] = nil
				end
			end
		end
		removeEventHandler(onElementDestroyEventName, this, removeDeletedElementTimer)
	end
	
	--[[
		Make a clean up cycle to prevent a memory leak
	]]
	local function checkCleanUpCycle (timeNow)
		if timeNow > nextCleanUpCycle then
			nextCleanUpCycle = timeNow + cleanUpInterval
			local maxExecutionTime = timeNow + 3
			for timerName, passiveTimers in pairs(passiveTimerGroups) do
				for key, executionTime in pairs(passiveTimers) do
					if timeNow > executionTime then
						if isElement(key) and isEventHandlerAdded(onElementDestroyEventName, key, removeDeletedElementTimer) then
							removeEventHandler(onElementDestroyEventName, key, removeDeletedElementTimer)
						end
						passiveTimers[key] = nil
					end
				end
				if not next(passiveTimers) then
					passiveTimerGroups[timerName] = nil
				end
				--[[
					Just making sure that during the clean-up cycle no lag spike occur.
				]]
				if getTickCount() >= maxExecutionTime then
					break
				end
			end
		end
	end
	
	function checkPassiveTimer (timerName, key, timeInterval)
		if type(timerName) ~= "string" then
			error("bad argument @ 'checkPassiveTimer' [Expected string at argument 1, got " .. type(timerName) .. "]", 2)
		elseif key == nil then
			error("bad argument @ 'checkPassiveTimer' [Expected anything except for nil at argument 2, got nil]", 2)
		end
		
		local intervalType = type(timeInterval)
		if intervalType == "string" then
			timeInterval = tonumber(timeInterval)
			if not timeInterval then
				error("bad argument @ 'checkPassiveTimer' [Expected a convertible string at argument 3]", 2)
			end
		elseif intervalType ~= "number" then
			error("bad argument @ 'checkPassiveTimer' [Expected number at argument 3, got " .. type(timeInterval) .. "]", 2)
		end
		
		--[[
			Set-up the timer
		]]
		local passiveTimers = passiveTimerGroups[timerName]
		if not passiveTimers then
			passiveTimers = {}
			passiveTimerGroups[timerName] = passiveTimers
		end
		
		local timeNow = getTickCount()


		local executionTime = passiveTimers[key]
		if executionTime then
			if timeNow > executionTime then
				passiveTimers[key] = timeNow + timeInterval
				checkCleanUpCycle(timeNow)
				return true, 0
			end
			checkCleanUpCycle(timeNow)
			return false, executionTime - timeNow
		end
		
		if isElement(key) and not isEventHandlerAdded(onElementDestroyEventName, key, removeDeletedElementTimer) then
			addEventHandler(onElementDestroyEventName, key, removeDeletedElementTimer, false, "high")
		end
		
		passiveTimers[key] = timeNow + timeInterval
		
		checkCleanUpCycle(timeNow)
		return true, 0
	end
end