<?php

namespace Kylin\Modules\Autoload;

use Illuminate\Filesystem\Filesystem;
use Kylin\Modules\ModuleManager;

/**
 * 模块自动加载器
 *
 * 负责自动加载模块中的类文件
 */
class Autoloader
{
    /**
     * 创建一个新的自动加载器实例
     *
     * @param  Filesystem  $files  文件系统实例
     * @param  ModuleManager  $moduleManager  模块管理器实例
     */
    public function __construct(
        private readonly Filesystem $files,
        private readonly ModuleManager $moduleManager
    ) {}

    /**
     * 注册自动加载器
     */
    public function register(): void
    {
        spl_autoload_register([$this, 'loadClass']);
    }

    /**
     * 注销自动加载器
     */
    public function unregister(): void
    {
        spl_autoload_unregister([$this, 'loadClass']);
    }

    /**
     * 加载类
     *
     * @param  string  $class  类名
     */
    public function loadClass(string $class): bool
    {
        return $this->loadModuleClass($class);
    }

    /**
     * 加载模块类
     *
     * @param  string  $class  类名
     */
    protected function loadModuleClass(string $class): bool
    {
        $modules = $this->moduleManager->all();

        foreach ($modules as $module) {
            $psr4 = $module->get('autoload.psr-4', []);

            foreach ($psr4 as $namespace => $path) {
                if (str_starts_with($class, $namespace)) {
                    $relativeClass = substr($class, strlen($namespace));
                    $file = $module->getExtraPath($path . '/' . str_replace('\\', '/', $relativeClass) . '.php');

                    if ($this->files->exists($file)) {
                        require_once $file;
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * 获取文件系统实例
     */
    public function getFilesystem(): Filesystem
    {
        return $this->files;
    }

    /**
     * 获取模块管理器实例
     */
    public function getModuleManager(): ModuleManager
    {
        return $this->moduleManager;
    }
}