local K=script.Parent local q=require(script.Parent.ScriptInfoUtils)local H=require(script.Parent.LoaderUtils)local r=require(script.Parent.BounceTemplateUtils)local G={}G.ClassName="\083\116\097\116\105\099\076\101\103\097\099\121\076\111\097\100\101\114"G.__index=G function G.new()local K=setmetatable({_packageLookups={}},G)return K end function G.__call(q,K)return q:Require(K)end function G.Lock(K)error("\067\097\110\110\111\116 \115\116\097\114\116 \108\111\097\100\101\114 \119\104\105\108\101 \110\111\116 \114\117\110\110\105\110\103")end function G.Require(H,K,q)if type(q)=="\110\117\109\098\101\114"then return require(q)elseif type(q)=="\115\116\114\105\110\103"then local r=H:_findModule(K,q)if r then H:_ensureFakeLoader(r)return require(r)else error("\069\114\114\111\114\058 \076\105\098\114\097\114\121 \'"..(tostring(q).."\' \100\111\101\115 \110\111\116 \101\120\105\115\116\046"),2)end elseif typeof(q)=="\073\110\115\116\097\110\099\101"and q:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then return require(q)else error(("\069\114\114\111\114\058 \109\111\100\117\108\101 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103 \111\114 \077\111\100\117\108\101\083\099\114\105\112\116\044 \103\111\116 \'\037\115\' \102\111\114 \'\037\115\'"):format(typeof(q),tostring(q)))end end function G._findModule(r,K,H)assert(typeof(K)=="\073\110\115\116\097\110\099\101","\066\097\100 \114\111\111\116")assert(type(H)=="\115\116\114\105\110\103","\066\097\100 \110\097\109\101")local G=r:_findPackageRoot(K)while G do local K=r:_getOrCreateLookup(G)if K[H]then return K[H]end local U=G:FindFirstChild(q.DEPENDENCY_FOLDER_NAME)if U then for K,q in pairs(U:GetChildren())do if q:IsA("\070\111\108\100\101\114")and q.Name:sub(1,1)=="\064"then for K,q in pairs(q:GetChildren())do local G=r:_getPackageFolderLookup(q)if G[H]then return G[H]end end else local K=r:_getPackageFolderLookup(q)if K[H]then return K[H]end end end end G=r:_findPackageRoot(G)end return nil end function G.GetLoader(q,K)assert(typeof(K)=="\073\110\115\116\097\110\099\101","\066\097\100 \109\111\100\117\108\101\083\099\114\105\112\116")return setmetatable({},{__call=function(H,r)return q:Require(K,r)end,__index=function(H,r)return q:Require(K,r)end})end function G._getPackageFolderLookup(q,K)if K:IsA("\079\098\106\101\099\116\086\097\108\117\101")then if K.Value then return q:_getOrCreateLookup(K.Value)else warn("\091\083\116\097\116\105\099\076\101\103\097\099\121\076\111\097\100\101\114\093 - \066\097\100 \108\105\110\107 \105\110 \112\097\099\107\097\103\101\070\111\108\100\101\114")return{}end elseif K:IsA("\070\111\108\100\101\114")then return q:_getOrCreateLookup(K)elseif K:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then return q:_getOrCreateLookup(K)else warn(("\085\110\107\110\111\119\110 \105\110\115\116\097\110\099\101 \037\113 \040\037\115\041 \105\110 \100\101\112\101\110\100\101\110\099\121\070\111\108\100\101\114 - \037\113"):format(K.Name,K.ClassName,K:GetFullName()))return{}end end function G._getOrCreateLookup(q,K)assert(typeof(K)=="\073\110\115\116\097\110\099\101","\066\097\100 \112\097\099\107\097\103\101\070\111\108\100\101\114\079\114\077\111\100\117\108\101\083\099\114\105\112\116")if q._packageLookups[K]then return q._packageLookups[K]end local H={}q:_buildLookup(H,K)q._packageLookups[K]=H return H end function G._buildLookup(r,K,H)if H:IsA("\070\111\108\100\101\114")then if H.Name~=q.DEPENDENCY_FOLDER_NAME then for q,H in pairs(H:GetChildren())do r:_buildLookup(K,H)end end elseif H:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")then K[H.Name]=H end end function G._findPackageRoot(q,K)assert(typeof(K)=="\073\110\115\116\097\110\099\101","\066\097\100 \105\110\115\116\097\110\099\101")local r=K.Parent while r and r~=game do if H.isPackage(r)then return r else r=r.Parent end end return nil end function G._ensureFakeLoader(H,q)assert(typeof(q)=="\073\110\115\116\097\110\099\101","\066\097\100 \109\111\100\117\108\101")local G=q.Parent if not G then warn("\091\083\116\097\116\105\099\076\101\103\097\099\121\076\111\097\100\101\114\093 - \078\111 \112\097\114\101\110\116")return end local U=Load and true or false local v=G:FindFirstChild("\108\111\097\100\101\114")if v then if r.isBounceTemplate(v)then v.Archivable=U end return end local M=r.create(K,"\108\111\097\100\101\114")M.Archivable=U M.Parent=G end return G
--[=[
	@private
	@class StaticLegacyLoader
]=]

local loader = script.Parent
local ScriptInfoUtils = require(script.Parent.ScriptInfoUtils)
local LoaderUtils = require(script.Parent.LoaderUtils)
local BounceTemplateUtils = require(script.Parent.BounceTemplateUtils)

local StaticLegacyLoader = {}
StaticLegacyLoader.ClassName = "StaticLegacyLoader"
StaticLegacyLoader.__index = StaticLegacyLoader

function StaticLegacyLoader.new()
	local self = setmetatable({
		_packageLookups = {},
	}, StaticLegacyLoader)

	return self
end

function StaticLegacyLoader:__call(value)
	return self:Require(value)
end

function StaticLegacyLoader:Lock()
	error("Cannot start loader while not running")
end

function StaticLegacyLoader:Require(root, value)
	if type(value) == "number" then
		return require(value)
	elseif type(value) == "string" then
		-- use very slow module recovery mechanism
		local module = self:_findModule(root, value)
		if module then
			self:_ensureFakeLoader(module)
			return require(module)
		else
			error("Error: Library '" .. tostring(value) .. "' does not exist.", 2)
		end
	elseif typeof(value) == "Instance" and value:IsA("ModuleScript") then
		return require(value)
	else
		error(
			("Error: module must be a string or ModuleScript, got '%s' for '%s'"):format(typeof(value), tostring(value))
		)
	end
end

function StaticLegacyLoader:_findModule(root, name)
	assert(typeof(root) == "Instance", "Bad root")
	assert(type(name) == "string", "Bad name")

	-- Implement the node_modules recursive find algorithm
	local packageRoot = self:_findPackageRoot(root)
	while packageRoot do
		-- Build lookup
		local highLevelLookup = self:_getOrCreateLookup(packageRoot)
		if highLevelLookup[name] then
			return highLevelLookup[name]
		end

		-- Ok, search our package dependencies
		local dependencies = packageRoot:FindFirstChild(ScriptInfoUtils.DEPENDENCY_FOLDER_NAME)
		if dependencies then
			for _, instance in pairs(dependencies:GetChildren()) do
				if instance:IsA("Folder") and instance.Name:sub(1, 1) == "@" then
					for _, child in pairs(instance:GetChildren()) do
						local lookup = self:_getPackageFolderLookup(child)
						if lookup[name] then
							return lookup[name]
						end
					end
				else
					local lookup = self:_getPackageFolderLookup(instance)
					if lookup[name] then
						return lookup[name]
					end
				end
			end
		end

		-- We failed to find anything... search up a level...
		packageRoot = self:_findPackageRoot(packageRoot)
	end

	return nil
end

function StaticLegacyLoader:GetLoader(moduleScript)
	assert(typeof(moduleScript) == "Instance", "Bad moduleScript")

	return setmetatable({}, {
		__call = function(_self, value)
			return self:Require(moduleScript, value)
		end,
		__index = function(_self, key)
			return self:Require(moduleScript, key)
		end,
	})
end

function StaticLegacyLoader:_getPackageFolderLookup(instance)
	if instance:IsA("ObjectValue") then
		if instance.Value then
			return self:_getOrCreateLookup(instance.Value)
		else
			warn("[StaticLegacyLoader] - Bad link in packageFolder")
			return {}
		end
	elseif instance:IsA("Folder") then
		return self:_getOrCreateLookup(instance)
	elseif instance:IsA("ModuleScript") then
		return self:_getOrCreateLookup(instance)
	else
		warn(
			("Unknown instance %q (%s) in dependencyFolder - %q"):format(
				instance.Name,
				instance.ClassName,
				instance:GetFullName()
			)
		)
		return {}
	end
end

function StaticLegacyLoader:_getOrCreateLookup(packageFolderOrModuleScript)
	assert(typeof(packageFolderOrModuleScript) == "Instance", "Bad packageFolderOrModuleScript")

	if self._packageLookups[packageFolderOrModuleScript] then
		return self._packageLookups[packageFolderOrModuleScript]
	end

	local lookup = {}

	self:_buildLookup(lookup, packageFolderOrModuleScript)

	self._packageLookups[packageFolderOrModuleScript] = lookup
	return lookup
end

function StaticLegacyLoader:_buildLookup(lookup, instance)
	if instance:IsA("Folder") then
		if instance.Name ~= ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
			for _, item in pairs(instance:GetChildren()) do
				self:_buildLookup(lookup, item)
			end
		end
	elseif instance:IsA("ModuleScript") then
		lookup[instance.Name] = instance
	end
end

function StaticLegacyLoader:_findPackageRoot(instance)
	assert(typeof(instance) == "Instance", "Bad instance")

	local current = instance.Parent

	while current and current ~= game do
		if LoaderUtils.isPackage(current) then
			return current
		else
			current = current.Parent
		end
	end

	return nil
end

function StaticLegacyLoader:_ensureFakeLoader(module)
	assert(typeof(module) == "Instance", "Bad module")

	local parent = module.Parent
	if not parent then
		warn("[StaticLegacyLoader] - No parent")
		return
	end

	-- NexusUnitTest
	-- luacheck: ignore
	-- selene: allow(undefined_variable)
	local shouldBeArchivable = Load and true or false

	-- Already have link
	local found = parent:FindFirstChild("loader")
	if found then
		if BounceTemplateUtils.isBounceTemplate(found) then
			found.Archivable = shouldBeArchivable
		end

		return
	end

	local link = BounceTemplateUtils.create(loader, "loader")
	link.Archivable = shouldBeArchivable
	link.Parent = parent
end

return StaticLegacyLoader
