--[[
local require = function(mod, ...)
	if mod and tonumber(mod) then
		warn("Requiring Module by ID; Expand for module URL > ", {URL = "https://www.roblox.com/library/".. moduleId})
	end

	return require(mod, ...)
end
--]]


function CloneTable(tab, recursive)
	local clone = table.clone(tab)

	if recursive then
		for i,v in pairs(clone) do
			if type(v) == "table" then
				clone[i] = CloneTable(v, recursive)
			end
		end
	end

	return clone
end

local function Pcall(func, ...)
	local pSuccess, pError = pcall(func, ...)
	if not pSuccess then
		warn(pError)
		logError(pError)
	end

	return pSuccess, pError
end

local function cPcall(func, ...)
	return Pcall(function(...)
		return coroutine.resume(coroutine.create(func), ...)
	end, ...)
end

local function Routine(func, ...)
	return coroutine.resume(coroutine.create(func), ...)
end

local function GetEnv(env, repl)
	local scriptEnv = setmetatable({}, {
		__index = function(tab, ind)
			return (locals[ind] or (env or origEnv)[ind])
		end;

		__metatable = unique;
	})
	if repl and type(repl) == "table" then
		for ind, val in pairs(repl) do
			scriptEnv[ind] = val
		end
	end
	return scriptEnv
end

local function GetVargTable()
	return {
		Server = server;
		Service = service;
	}
end

local function LoadModule(plugin, yield, envVars, noEnv, isCore)
	noEnv = false --// Seems to make loading take longer when true (?)
	local isFunc = type(plugin) == "function"
	local plugin = (isFunc and service.New("ModuleScript", {Name = "Non-Module Loaded"})) or plugin
	local plug = (isFunc and plugin) or require(plugin)

	if server.Modules and type(plugin) ~= "function" then
		table.insert(server.Modules,plugin)
	end

	if type(plug) == "function" then
		if isCore then
			local ran,err = service.TrackTask("CoreModule: ".. tostring(plugin), plug, GetVargTable(), GetEnv)
			if not ran then
				warn("Core Module encountered an error while loading:", plugin)
				warn(err)
			else
				return err;
			end
		elseif yield then
			--Pcall(setfenv(plug,GetEnv(getfenv(plug), envVars)))
			local ran,err = service.TrackTask("Plugin: ".. tostring(plugin), (noEnv and plug) or setfenv(plug, GetEnv(getfenv(plug), envVars)), GetVargTable())
			if not ran then
				warn("Module encountered an error while loading:", plugin)
				warn(err)
			else
				return err;
			end
		else
			--service.Threads.RunTask("PLUGIN: "..tostring(plugin),setfenv(plug,GetEnv(getfenv(plug), envVars)))
			local ran, err = service.TrackTask("Thread: Plugin: ".. tostring(plugin), (noEnv and plug) or setfenv(plug, GetEnv(getfenv(plug), envVars)), GetVargTable())
			if not ran then
				warn("Module encountered an error while loading:", plugin)
				warn(err)
			else
				return err;
			end
		end
	else
		server[plugin.Name] = plug
	end

	if server.Logs then
		server.Logs.AddLog(server.Logs.Script,{
			Text = "Loaded "..tostring(plugin).." Module";
			Desc = "Adonis loaded a core module or plugin";
		})
	end
end;
