"use strict";
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
    var useValue = arguments.length > 2;
    for (var i = 0; i < initializers.length; i++) {
        value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
    }
    return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
    function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
    var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
    var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
    var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
    var _, done = false;
    for (var i = decorators.length - 1; i >= 0; i--) {
        var context = {};
        for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
        for (var p in contextIn.access) context.access[p] = contextIn.access[p];
        context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
        var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
        if (kind === "accessor") {
            if (result === void 0) continue;
            if (result === null || typeof result !== "object") throw new TypeError("Object expected");
            if (_ = accept(result.get)) descriptor.get = _;
            if (_ = accept(result.set)) descriptor.set = _;
            if (_ = accept(result.init)) initializers.unshift(_);
        }
        else if (_ = accept(result)) {
            if (kind === "field") initializers.unshift(_);
            else descriptor[key] = _;
        }
    }
    if (target) Object.defineProperty(target, contextIn.name, descriptor);
    done = true;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
    if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
    return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const explainable_cursor_1 = __importDefault(require("./explainable-cursor"));
const decorators_1 = require("./decorators");
const enums_1 = require("./enums");
const helpers_1 = require("./helpers");
let Explainable = (() => {
    let _classDecorators = [decorators_1.shellApiClassDefault];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = decorators_1.ShellApiWithMongoClass;
    let _instanceExtraInitializers = [];
    let _find_decorators;
    let _aggregate_decorators;
    let _count_decorators;
    let _distinct_decorators;
    let _findAndModify_decorators;
    let _findOneAndDelete_decorators;
    let _findOneAndReplace_decorators;
    let _findOneAndUpdate_decorators;
    let _remove_decorators;
    let _update_decorators;
    let _mapReduce_decorators;
    var Explainable = _classThis = class extends _classSuper {
        constructor(mongo, collection, verbosity) {
            super();
            this._mongo = __runInitializers(this, _instanceExtraInitializers);
            this._mongo = mongo;
            this._collection = collection;
            this._verbosity = verbosity;
        }
        [enums_1.asPrintable]() {
            return `Explainable(${this._collection.getFullName()})`;
        }
        _emitExplainableApiCall(methodName, methodArguments = {}) {
            this._mongo._instanceState.emitApiCallWithArgs({
                method: methodName,
                class: 'Explainable',
                db: this._collection._database._name,
                coll: this._collection._name,
                arguments: methodArguments,
            });
        }
        getCollection() {
            this._emitExplainableApiCall('getCollection');
            return this._collection;
        }
        getVerbosity() {
            this._emitExplainableApiCall('getVerbosity');
            return this._verbosity;
        }
        setVerbosity(verbosity) {
            verbosity = (0, helpers_1.validateExplainableVerbosity)(verbosity);
            this._emitExplainableApiCall('setVerbosity', { verbosity });
            this._verbosity = verbosity;
        }
        async find(query, projection, options = {}) {
            this._emitExplainableApiCall('find', { query, projection });
            const cursor = await this._collection.find(query, projection, options);
            return new explainable_cursor_1.default(this._mongo, cursor, this._verbosity);
        }
        async aggregate(...args) {
            this._emitExplainableApiCall('aggregate', { args });
            let options;
            let pipeline;
            if (Array.isArray(args[0])) {
                pipeline = args[0];
                options = args[1] ?? {};
            }
            else {
                pipeline = args;
                options = {};
            }
            return await this._collection.aggregate(pipeline, {
                ...options,
                explain: this._verbosity,
            });
        }
        async count(query = {}, options = {}) {
            this._emitExplainableApiCall('count', { query, options });
            return (0, helpers_1.markAsExplainOutput)(await this._collection._database._runReadCommand({
                explain: {
                    count: `${this._collection._name}`,
                    query,
                    ...options,
                },
                verbosity: this._verbosity,
            }));
        }
        async distinct(field, query, options = {}) {
            this._emitExplainableApiCall('distinct', { field, query, options });
            return this._collection.distinct(field, query ?? {}, {
                ...options,
                explain: this._verbosity,
            });
        }
        async findAndModify(options) {
            this._emitExplainableApiCall('findAndModify', { options });
            return this._collection.findAndModify({
                ...options,
                explain: this._verbosity,
            });
        }
        async findOneAndDelete(filter, options = {}) {
            this._emitExplainableApiCall('findOneAndDelete', { filter, options });
            return this._collection.findOneAndDelete(filter, {
                ...options,
                explain: this._verbosity,
            });
        }
        async findOneAndReplace(filter, replacement, options = {}) {
            this._emitExplainableApiCall('findOneAndReplace', { filter, options });
            return this._collection.findOneAndReplace(filter, replacement, {
                ...options,
                explain: this._verbosity,
            });
        }
        async findOneAndUpdate(filter, update, options = {}) {
            this._emitExplainableApiCall('findOneAndUpdate', { filter, options });
            return this._collection.findOneAndUpdate(filter, update, {
                ...options,
                explain: this._verbosity,
            });
        }
        async remove(query, options = {}) {
            this._emitExplainableApiCall('remove', { query, options });
            options = { ...(0, helpers_1.processRemoveOptions)(options), explain: this._verbosity };
            return this._collection.remove(query, options);
        }
        async update(filter, update, options = {}) {
            this._emitExplainableApiCall('update', { filter, update, options });
            return this._collection.update(filter, update, {
                ...options,
                explain: this._verbosity,
            });
        }
        async mapReduce(map, reduce, optionsOrOutString) {
            this._emitExplainableApiCall('mapReduce', {
                map,
                reduce,
                optionsOrOutString,
            });
            const options = {
                ...(0, helpers_1.processMapReduceOptions)(optionsOrOutString),
                explain: this._verbosity,
            };
            return this._collection.mapReduce(map, reduce, options);
        }
    };
    __setFunctionName(_classThis, "Explainable");
    (() => {
        const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
        _find_decorators = [(0, decorators_1.returnType)('ExplainableCursor'), (0, decorators_1.apiVersions)([1]), decorators_1.returnsPromise];
        _aggregate_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _count_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _distinct_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _findAndModify_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _findOneAndDelete_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _findOneAndReplace_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _findOneAndUpdate_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _remove_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _update_decorators = [decorators_1.returnsPromise, (0, decorators_1.apiVersions)([1])];
        _mapReduce_decorators = [decorators_1.returnsPromise, (0, decorators_1.serverVersions)(['4.4.0', enums_1.ServerVersions.latest]), (0, decorators_1.apiVersions)([])];
        __esDecorate(_classThis, null, _find_decorators, { kind: "method", name: "find", static: false, private: false, access: { has: obj => "find" in obj, get: obj => obj.find }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _aggregate_decorators, { kind: "method", name: "aggregate", static: false, private: false, access: { has: obj => "aggregate" in obj, get: obj => obj.aggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _count_decorators, { kind: "method", name: "count", static: false, private: false, access: { has: obj => "count" in obj, get: obj => obj.count }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _distinct_decorators, { kind: "method", name: "distinct", static: false, private: false, access: { has: obj => "distinct" in obj, get: obj => obj.distinct }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _findAndModify_decorators, { kind: "method", name: "findAndModify", static: false, private: false, access: { has: obj => "findAndModify" in obj, get: obj => obj.findAndModify }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _findOneAndDelete_decorators, { kind: "method", name: "findOneAndDelete", static: false, private: false, access: { has: obj => "findOneAndDelete" in obj, get: obj => obj.findOneAndDelete }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _findOneAndReplace_decorators, { kind: "method", name: "findOneAndReplace", static: false, private: false, access: { has: obj => "findOneAndReplace" in obj, get: obj => obj.findOneAndReplace }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _findOneAndUpdate_decorators, { kind: "method", name: "findOneAndUpdate", static: false, private: false, access: { has: obj => "findOneAndUpdate" in obj, get: obj => obj.findOneAndUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _remove_decorators, { kind: "method", name: "remove", static: false, private: false, access: { has: obj => "remove" in obj, get: obj => obj.remove }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _update_decorators, { kind: "method", name: "update", static: false, private: false, access: { has: obj => "update" in obj, get: obj => obj.update }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(_classThis, null, _mapReduce_decorators, { kind: "method", name: "mapReduce", static: false, private: false, access: { has: obj => "mapReduce" in obj, get: obj => obj.mapReduce }, metadata: _metadata }, null, _instanceExtraInitializers);
        __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
        Explainable = _classThis = _classDescriptor.value;
        if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        __runInitializers(_classThis, _classExtraInitializers);
    })();
    return Explainable = _classThis;
})();
exports.default = Explainable;
//# sourceMappingURL=explainable.js.map