import { Trie } from "@wry/trie";
import { canUseWeakMap, canUseWeakSet } from "../common/canUse.js";
import { checkDocument } from "./getFromAST.js";
import { invariant } from "../globals/index.js";
import { WeakCache } from "@wry/caches";
import { wrap } from "optimism";
import { cacheSizes } from "../caching/index.js";
function identity(document) {
    return document;
}
var DocumentTransform = /** @class */ (function () {
    function DocumentTransform(transform, options) {
        if (options === void 0) { options = Object.create(null); }
        this.resultCache = canUseWeakSet ? new WeakSet() : new Set();
        this.transform = transform;
        if (options.getCacheKey) {
            // Override default `getCacheKey` function, which returns [document].
            this.getCacheKey = options.getCacheKey;
        }
        this.cached = options.cache !== false;
        this.resetCache();
    }
    // This default implementation of getCacheKey can be overridden by providing
    // options.getCacheKey to the DocumentTransform constructor. In general, a
    // getCacheKey function may either return an array of keys (often including
    // the document) to be used as a cache key, or undefined to indicate the
    // transform for this document should not be cached.
    DocumentTransform.prototype.getCacheKey = function (document) {
        return [document];
    };
    DocumentTransform.identity = function () {
        // No need to cache this transform since it just returns the document
        // unchanged. This should save a bit of memory that would otherwise be
        // needed to populate the `documentCache` of this transform.
        return new DocumentTransform(identity, { cache: false });
    };
    DocumentTransform.split = function (predicate, left, right) {
        if (right === void 0) { right = DocumentTransform.identity(); }
        return Object.assign(new DocumentTransform(function (document) {
            var documentTransform = predicate(document) ? left : right;
            return documentTransform.transformDocument(document);
        }, 
        // Reasonably assume both `left` and `right` transforms handle their own caching
        { cache: false }), { left: left, right: right });
    };
    /**
     * Resets the internal cache of this transform, if it has one.
     */
    DocumentTransform.prototype.resetCache = function () {
        var _this = this;
        if (this.cached) {
            var stableCacheKeys_1 = new Trie(canUseWeakMap);
            this.performWork = wrap(DocumentTransform.prototype.performWork.bind(this), {
                makeCacheKey: function (document) {
                    var cacheKeys = _this.getCacheKey(document);
                    if (cacheKeys) {
                        invariant(Array.isArray(cacheKeys), 66);
                        return stableCacheKeys_1.lookupArray(cacheKeys);
                    }
                },
                max: cacheSizes["documentTransform.cache"],
                cache: (WeakCache),
            });
        }
    };
    DocumentTransform.prototype.performWork = function (document) {
        checkDocument(document);
        return this.transform(document);
    };
    DocumentTransform.prototype.transformDocument = function (document) {
        // If a user passes an already transformed result back to this function,
        // immediately return it.
        if (this.resultCache.has(document)) {
            return document;
        }
        var transformedDocument = this.performWork(document);
        this.resultCache.add(transformedDocument);
        return transformedDocument;
    };
    DocumentTransform.prototype.concat = function (otherTransform) {
        var _this = this;
        return Object.assign(new DocumentTransform(function (document) {
            return otherTransform.transformDocument(_this.transformDocument(document));
        }, 
        // Reasonably assume both transforms handle their own caching
        { cache: false }), {
            left: this,
            right: otherTransform,
        });
    };
    return DocumentTransform;
}());
export { DocumentTransform };
//# sourceMappingURL=DocumentTransform.js.map