-- Copyright (C) 2025 ASTRONAND
local args=({...})[1]
local log=args.logging
local fs=args.filesystem
local loaded=args.preload or {}
local function dot_to_slash(name)
    local parts = {}
    local start = 1
    for i = 1, #name do
        if name:sub(i, i) == "." then
            table.insert(parts, name:sub(start, i - 1))
            start = i + 1
        end
    end
    table.insert(parts, name:sub(start))
    return table.concat(parts, "/")
end

local function replace_question_mark(path, name_path)
    local result = {}
    local replaced = false
    for i = 1, #path do
        local ch = path:sub(i, i)
        if ch == "?" and not replaced then
            table.insert(result, name_path)
            replaced = true
        else
            table.insert(result, ch)
        end
    end
    return table.concat(result)
end

local function search_module(name,search_paths)
    local name_path = dot_to_slash(name)

    for _, path in ipairs(search_paths) do
        local filename = replace_question_mark(path, name_path)
        if fs.exists(filename) and not fs.isDir(filename) then
            local code=fs.open(filename,"x")
            if code then
                return code, filename
            end
        end
    end

    return nil, "module not found: " .. name
end

return {
    makeRequire=function(search_paths)
        local config=string.split(search_paths,";")
        return {
            require=function(query)
                if loaded[query] then return table.deepcopy(loaded[query]) end
                local code,file=search_module(query,config)
                if code==nil then
                    error(file)
                end
                local ok,_,lib=pcall(pcall,code)
                if ok then
                    log.log("Added: \""..query.."\" to require registry.")
                    loaded[query]=lib
                    return table.deepcopy(lib), file
                else
                    log.warn("ERR in module "..file)
                    return nil, "ERR in module "..file.."."
                end
            end,
            load=function(query, lib)
                loaded[query]=lib
            end
        }
    end,
    list=function()
        local list={}
        for i,v in pairs(loaded) do
            list[#list+1]={i=i,v=v}
        end
        local i=0
        while i<#list do
            i=i+1
            return list[i].i, list[i].v
        end
    end
}