public static function findModules(string $path, string $module_name_prefix, int $depth)
    {
        if (!is_dir($path))
            throw new \InvalidArgumentException("Not a path: $path");

        $dirs = dir($path);

        $modules = array();
        while ($dir = $dirs->read())
        {
            if ($dir === ".." || $dir === ".")
                continue;

            $mod_path = $path . DIRECTORY_SEPARATOR . $dir;
            if (!is_dir($mod_path))
                continue;

            $dirname = ucfirst(strtolower($dir));
            $module_name = $module_name_prefix . $dirname;
            if ($depth > 0)
            {
                $sub_modules = self::findModules($mod_path, $module_name . '.', $depth - 1);
                $modules = array_merge($modules, $sub_modules);
            }
            else
            {
                $modules[$module_name] = $mod_path;
            }
        }

        return $modules;
    }