/**
 * @copyright Sister Software
 * @license AGPL-3.0
 * @author Teffen Ellis, et al.
 */
/**
 * Type-guard to determine if a function is a constructor.
 */
function isConstructor(value) {
    if (typeof value !== "function")
        return false;
    return Boolean(value.prototype && value.prototype.constructor === value);
}
/**
 * Type-guard to determine if a value is a promise-like object.
 */
export function isPromiseLike(value) {
    if (typeof value !== "object" || value === null)
        return false;
    return typeof value.then === "function";
}
/**
 * A map-like object that caches disposable resources, creating them on demand.
 */
export class ResourceMapCache extends Map {
    factoryLike;
    /**
     * The human-readable name of the resource.
     */
    displayName = "ResourceMapCache";
    constructor(factoryLike) {
        super();
        this.factoryLike = factoryLike;
    }
    /**
     * Gets a resource from the cache, creating if it doesn't exist.
     */
    open(key) {
        const existingResource = super.get(key);
        if (existingResource)
            return existingResource;
        if (isConstructor(this.factoryLike)) {
            const resource = new this.factoryLike(key);
            super.set(key, resource);
            return resource;
        }
        const factoryResult = this.factoryLike(key);
        if (isPromiseLike(factoryResult)) {
            return factoryResult.then((resolvedResource) => {
                super.set(key, resolvedResource);
                return resolvedResource;
            });
        }
        super.set(key, factoryResult);
        return factoryResult;
    }
    /**
     * Closes a resource and removes it from the cache.
     */
    close(key) {
        const resource = super.get(key);
        if (resource && Symbol.dispose in resource) {
            resource[Symbol.dispose]();
        }
        super.delete(key);
    }
    async [Symbol.asyncDispose]() {
        const resourceKeys = Array.from(super.keys()).reverse();
        for (const resourceKey of resourceKeys) {
            this.close(resourceKey);
        }
        super.clear();
    }
}
//# sourceMappingURL=ResourceMapCache.js.map