"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessagesGetHandler = void 0;
const data_stream_js_1 = require("../utils/data-stream.js");
const dwn_constant_js_1 = require("../core/dwn-constant.js");
const encoder_js_1 = require("../utils/encoder.js");
const message_reply_js_1 = require("../core/message-reply.js");
const messages_get_js_1 = require("../interfaces/messages-get.js");
const auth_js_1 = require("../core/auth.js");
const message_js_1 = require("../core/message.js");
class MessagesGetHandler {
    constructor(didResolver, messageStore, dataStore) {
        this.didResolver = didResolver;
        this.messageStore = messageStore;
        this.dataStore = dataStore;
    }
    handle({ tenant, message }) {
        return __awaiter(this, void 0, void 0, function* () {
            let messagesGet;
            try {
                messagesGet = yield messages_get_js_1.MessagesGet.parse(message);
            }
            catch (e) {
                return (0, message_reply_js_1.messageReplyFromError)(e, 400);
            }
            try {
                yield (0, auth_js_1.authenticate)(message.authorization, this.didResolver);
                yield (0, auth_js_1.authorize)(tenant, messagesGet);
            }
            catch (e) {
                return (0, message_reply_js_1.messageReplyFromError)(e, 401);
            }
            const promises = [];
            const messageCids = new Set(message.descriptor.messageCids);
            for (const messageCid of messageCids) {
                const promise = this.messageStore.get(tenant, messageCid)
                    .then(message => {
                    return { messageCid, message };
                })
                    .catch(_ => {
                    return { messageCid, message: undefined, error: `Failed to get message ${messageCid}` };
                });
                promises.push(promise);
            }
            const messages = yield Promise.all(promises);
            // for every message, include associated data as `encodedData` IF:
            //  * its a RecordsWrite
            //  * the data size is equal or smaller than the size threshold
            //! NOTE: this is somewhat duplicate code that also exists in `StorageController.query`.
            for (const entry of messages) {
                const { message } = entry;
                if (!message) {
                    continue;
                }
                const { interface: messageInterface, method } = message.descriptor;
                if (messageInterface !== message_js_1.DwnInterfaceName.Records || method !== message_js_1.DwnMethodName.Write) {
                    continue;
                }
                // RecordsWrite specific handling
                const recordsWrite = message;
                const dataCid = recordsWrite.descriptor.dataCid;
                const dataSize = recordsWrite.descriptor.dataSize;
                if (dataCid !== undefined && dataSize <= dwn_constant_js_1.DwnConstant.maxDataSizeAllowedToBeEncoded) {
                    const messageCid = yield message_js_1.Message.getCid(message);
                    const result = yield this.dataStore.get(tenant, messageCid, dataCid);
                    if (result) {
                        const dataBytes = yield data_stream_js_1.DataStream.toBytes(result.dataStream);
                        entry.encodedData = encoder_js_1.Encoder.bytesToBase64Url(dataBytes);
                    }
                }
            }
            return {
                status: { code: 200, detail: 'OK' },
                messages
            };
        });
    }
}
exports.MessagesGetHandler = MessagesGetHandler;
//# sourceMappingURL=messages-get.js.map