import { assertInjectable } from "./Injectable";
import { GetClassName } from "./ClassName";

/**
 * 一个简单的类容器
 */
export class Container {
    static _container = new Map();
    private static logger;

    static set(k: any, v: any): void {
        if (!this._container.has(k)) {
            this._container.set(k, v);
        }
    }

    static get(k: any): any {
        return this._container.get(k);
    }

    static factory<T>(target: Constructor<T>): T {
        assertInjectable(target);
        // if (Container.get(target))
        //     return Container.get(target);
        return this.get(target) || this.initParam(target);
    }

    static setLogger(logger: { info(...o: any[]), error(...o: any[]), warn(...o: any[]) }): void {
        this.logger = logger;
    }

    private static initParam<T>(target: Constructor<T>): T {
        // 获取所有注入的服务
        const providers = Reflect.getMetadata('design:paramtypes', target);
        // this.logger.info({providers})
        // this.logger.info('原型名'+Object.getPrototypeOf(target).constructor.name)
        // this.logger.info('直接名'+target.name)
        const args = providers ? providers.map((provider: Constructor) => {
            return this.factory(provider);
        }) : [];
        let _target = new target(...args);
        this.logger?.info(
            `[${ GetClassName(target) || target.name }] 实例化`
        );
        this.set(target, _target);
        return _target;
    }
}
