"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageStoreLevel = void 0;
var block = __importStar(require("multiformats/block"));
var cbor = __importStar(require("@ipld/dag-cbor"));
var blockstore_level_js_1 = require("./blockstore-level.js");
var cid_1 = require("multiformats/cid");
var level_wrapper_js_1 = require("./level-wrapper.js");
var abort_js_1 = require("../utils/abort.js");
var index_level_js_1 = require("./index-level.js");
var sha2_1 = require("multiformats/hashes/sha2");
/**
 * A simple implementation of {@link MessageStore} that works in both the browser and server-side.
 * Leverages LevelDB under the hood.
 */
var MessageStoreLevel = /** @class */ (function () {
    /**
     * @param {MessageStoreLevelConfig} config
     * @param {string} config.blockstoreLocation - must be a directory path (relative or absolute) where
     *  LevelDB will store its files, or in browsers, the name of the
     * {@link https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase IDBDatabase} to be opened.
     * @param {string} config.indexLocation - same as config.blockstoreLocation
     */
    function MessageStoreLevel(config) {
        if (config === void 0) { config = {}; }
        this.config = __assign({ blockstoreLocation: 'MESSAGESTORE', indexLocation: 'INDEX', createLevelDatabase: level_wrapper_js_1.createLevelDatabase }, config);
        this.blockstore = new blockstore_level_js_1.BlockstoreLevel({
            location: this.config.blockstoreLocation,
            createLevelDatabase: this.config.createLevelDatabase,
        });
        this.index = new index_level_js_1.IndexLevel({
            location: this.config.indexLocation,
            createLevelDatabase: this.config.createLevelDatabase,
        });
    }
    MessageStoreLevel.prototype.open = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.blockstore.open()];
                    case 1:
                        _a.sent();
                        return [4 /*yield*/, this.index.open()];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    MessageStoreLevel.prototype.close = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.blockstore.close()];
                    case 1:
                        _a.sent();
                        return [4 /*yield*/, this.index.close()];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    MessageStoreLevel.prototype.get = function (tenant, cidString, options) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var partition, cid, bytes, decodedBlock, messageJson;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        (_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
                        return [4 /*yield*/, (0, abort_js_1.executeUnlessAborted)(this.blockstore.partition(tenant), options === null || options === void 0 ? void 0 : options.signal)];
                    case 1:
                        partition = _b.sent();
                        cid = cid_1.CID.parse(cidString);
                        return [4 /*yield*/, partition.get(cid, options)];
                    case 2:
                        bytes = _b.sent();
                        if (!bytes) {
                            return [2 /*return*/, undefined];
                        }
                        return [4 /*yield*/, (0, abort_js_1.executeUnlessAborted)(block.decode({ bytes: bytes, codec: cbor, hasher: sha2_1.sha256 }), options === null || options === void 0 ? void 0 : options.signal)];
                    case 3:
                        decodedBlock = _b.sent();
                        messageJson = decodedBlock.value;
                        return [2 /*return*/, messageJson];
                }
            });
        });
    };
    MessageStoreLevel.prototype.query = function (tenant, filter, options) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var messages, resultIds, resultIds_1, resultIds_1_1, id, message, e_1_1;
            var e_1, _b;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        (_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
                        messages = [];
                        return [4 /*yield*/, this.index.query(__assign(__assign({}, filter), { tenant: tenant }), options)];
                    case 1:
                        resultIds = _c.sent();
                        _c.label = 2;
                    case 2:
                        _c.trys.push([2, 7, 8, 9]);
                        resultIds_1 = __values(resultIds), resultIds_1_1 = resultIds_1.next();
                        _c.label = 3;
                    case 3:
                        if (!!resultIds_1_1.done) return [3 /*break*/, 6];
                        id = resultIds_1_1.value;
                        return [4 /*yield*/, this.get(tenant, id, options)];
                    case 4:
                        message = _c.sent();
                        if (message) {
                            messages.push(message);
                        }
                        _c.label = 5;
                    case 5:
                        resultIds_1_1 = resultIds_1.next();
                        return [3 /*break*/, 3];
                    case 6: return [3 /*break*/, 9];
                    case 7:
                        e_1_1 = _c.sent();
                        e_1 = { error: e_1_1 };
                        return [3 /*break*/, 9];
                    case 8:
                        try {
                            if (resultIds_1_1 && !resultIds_1_1.done && (_b = resultIds_1.return)) _b.call(resultIds_1);
                        }
                        finally { if (e_1) throw e_1.error; }
                        return [7 /*endfinally*/];
                    case 9: return [2 /*return*/, messages];
                }
            });
        });
    };
    MessageStoreLevel.prototype.delete = function (tenant, cidString, options) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var partition, cid;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        (_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
                        return [4 /*yield*/, (0, abort_js_1.executeUnlessAborted)(this.blockstore.partition(tenant), options === null || options === void 0 ? void 0 : options.signal)];
                    case 1:
                        partition = _b.sent();
                        cid = cid_1.CID.parse(cidString);
                        return [4 /*yield*/, partition.delete(cid, options)];
                    case 2:
                        _b.sent();
                        return [4 /*yield*/, this.index.delete(cidString, options)];
                    case 3:
                        _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    MessageStoreLevel.prototype.put = function (tenant, message, indexes, options) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var partition, encodedMessageBlock, encodedMessageBlockCid, indexDocument;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        (_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
                        return [4 /*yield*/, (0, abort_js_1.executeUnlessAborted)(this.blockstore.partition(tenant), options === null || options === void 0 ? void 0 : options.signal)];
                    case 1:
                        partition = _b.sent();
                        return [4 /*yield*/, (0, abort_js_1.executeUnlessAborted)(block.encode({ value: message, codec: cbor, hasher: sha2_1.sha256 }), options === null || options === void 0 ? void 0 : options.signal)];
                    case 2:
                        encodedMessageBlock = _b.sent();
                        return [4 /*yield*/, partition.put(encodedMessageBlock.cid, encodedMessageBlock.bytes, options)];
                    case 3:
                        _b.sent();
                        encodedMessageBlockCid = encodedMessageBlock.cid.toString();
                        indexDocument = __assign(__assign({}, indexes), { tenant: tenant });
                        return [4 /*yield*/, this.index.put(encodedMessageBlockCid, indexDocument, options)];
                    case 4:
                        _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * deletes everything in the underlying blockstore and indices.
     */
    MessageStoreLevel.prototype.clear = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.blockstore.clear()];
                    case 1:
                        _a.sent();
                        return [4 /*yield*/, this.index.clear()];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    MessageStoreLevel.prototype.dump = function () {
        var _a, _b, _c, _d;
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0:
                        console.group('blockstore');
                        return [4 /*yield*/, ((_b = (_a = this.blockstore)['dump']) === null || _b === void 0 ? void 0 : _b.call(_a))];
                    case 1:
                        _e.sent();
                        console.groupEnd();
                        console.group('index');
                        return [4 /*yield*/, ((_d = (_c = this.index)['dump']) === null || _d === void 0 ? void 0 : _d.call(_c))];
                    case 2:
                        _e.sent();
                        console.groupEnd();
                        return [2 /*return*/];
                }
            });
        });
    };
    return MessageStoreLevel;
}());
exports.MessageStoreLevel = MessageStoreLevel;
//# sourceMappingURL=message-store-level.js.map