

let instanceMap = new Map();

export interface PrototypeType<T> extends Function {
    prototype: T;
}

export interface ConstructorFunctionType<T = any> extends PrototypeType<T> {
    new(...args: any[]): T;
}

export type ConstructorType<T = unknown, Static extends Record<string, any> = PrototypeType<T>> = (ConstructorFunctionType<T> | PrototypeType<T>) & {
    [Key in keyof Static]: Static[Key];
};

/**
 * 构造单例类的静态类.
 * # Example:
 *     class A extends Singleton(){};
 *     //获得单例
 *     let a = A.GetInstance();
 */
export class Singleton {
    protected constructor() { }

    //ref:https://github.com/Microsoft/TypeScript/issues/5863
    static GetInstance<T extends Singleton>(this: ConstructorType<T, typeof Singleton>): T {
        if (instanceMap.has(this))
            return instanceMap.get(this);
        //@ts-ignore
        let __instance__ = new this.prototype.constructor();
        instanceMap.set(this, __instance__);
        return __instance__;
    }

    /**
    * 释放指定类型的单例实例。
    * @returns {boolean} 如果实例存在并被释放则返回 true，否则返回 false。
    */
    static ReleaseInstance<T extends Singleton>(this: ConstructorType<T, typeof Singleton>): boolean {
        if (instanceMap.has(this)) {
            const instance = instanceMap.get(this);
            // 如果实例有清理方法，可以在这里调用
            if (typeof (instance as any).dispose === 'function') {
                (instance as any).dispose();
            }
            instanceMap.delete(this);
            console.log(`Singleton instance of ${this.name} has been released.`);
            return true;
        }
        console.log(`No singleton instance of ${this.name} found to release.`);
        return false;
    }
}
