"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StreamMessage = exports.StreamMessageType = void 0;
const utils_1 = require("@streamr/utils");
const trackerless_network_1 = require("@streamr/trackerless-network");
const StreamrClientError_1 = require("../StreamrClientError");
const MessageRef_1 = require("./MessageRef");
const ValidationError_1 = require("./ValidationError");
const validations_1 = require("./validations");
var StreamMessageType;
(function (StreamMessageType) {
    StreamMessageType[StreamMessageType["MESSAGE"] = 0] = "MESSAGE";
    StreamMessageType[StreamMessageType["GROUP_KEY_REQUEST"] = 1] = "GROUP_KEY_REQUEST";
    StreamMessageType[StreamMessageType["GROUP_KEY_RESPONSE"] = 2] = "GROUP_KEY_RESPONSE";
})(StreamMessageType || (exports.StreamMessageType = StreamMessageType = {}));
/**
 * Validates that messageId is strictly after prevMsgRef in time.
 */
function validateSequence(messageId, prevMsgRef) {
    if (prevMsgRef === undefined) {
        return;
    }
    const comparison = messageId.toMessageRef().compareTo(prevMsgRef);
    if (comparison === 0) {
        throw new ValidationError_1.ValidationError(
        // eslint-disable-next-line max-len
        `prevMessageRef cannot be identical to current. Current: ${JSON.stringify(messageId.toMessageRef())} Previous: ${JSON.stringify(prevMsgRef)}`);
    }
    if (comparison < 0) {
        throw new ValidationError_1.ValidationError(`prevMessageRef must come before current. Current: ${JSON.stringify(messageId.toMessageRef())} Previous: ${JSON.stringify(prevMsgRef)}`);
    }
}
/**
 * An internal class representing a message in a stream. Applications see instances of the Message class.
 */
class StreamMessage {
    messageId;
    prevMsgRef;
    messageType;
    content;
    contentType;
    signature;
    signatureType;
    encryptionType;
    groupKeyId;
    newGroupKey;
    constructor({ messageId, prevMsgRef, messageType = StreamMessageType.MESSAGE, content, contentType, signature, signatureType, encryptionType, groupKeyId, newGroupKey, }) {
        validateSequence(messageId, prevMsgRef);
        if (encryptionType === trackerless_network_1.EncryptionType.AES) {
            (0, validations_1.validateIsDefined)('groupKeyId', groupKeyId);
        }
        this.messageId = messageId;
        this.prevMsgRef = prevMsgRef;
        this.messageType = messageType;
        this.contentType = contentType;
        this.encryptionType = encryptionType;
        this.groupKeyId = groupKeyId;
        this.newGroupKey = newGroupKey;
        this.signature = signature;
        this.signatureType = signatureType;
        this.content = content;
    }
    getStreamId() {
        return this.messageId.streamId;
    }
    getStreamPartition() {
        return this.messageId.streamPartition;
    }
    getStreamPartID() {
        return this.messageId.getStreamPartID();
    }
    getTimestamp() {
        return this.messageId.timestamp;
    }
    getSequenceNumber() {
        return this.messageId.sequenceNumber;
    }
    getPublisherId() {
        return this.messageId.publisherId;
    }
    getMsgChainId() {
        return this.messageId.msgChainId;
    }
    getMessageRef() {
        return new MessageRef_1.MessageRef(this.getTimestamp(), this.getSequenceNumber());
    }
    // TODO: consider replacing later half of type with a "JSON type" from a ts-toolbelt or type-fest or ts-essentials
    getParsedContent() {
        if (this.encryptionType !== trackerless_network_1.EncryptionType.NONE || this.contentType === trackerless_network_1.ContentType.BINARY) {
            return this.content;
        }
        else if (this.contentType === trackerless_network_1.ContentType.JSON) {
            try {
                return JSON.parse((0, utils_1.binaryToUtf8)(this.content));
            }
            catch (err) {
                // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
                throw new StreamrClientError_1.StreamrClientError(`Unable to parse JSON: ${err}`, 'INVALID_MESSAGE_CONTENT', this);
            }
        }
        else {
            throw new StreamrClientError_1.StreamrClientError(`Unknown content type: ${this.contentType}`, 'ASSERTION_FAILED', this);
        }
    }
    static isAESEncrypted(msg) {
        return msg.encryptionType === trackerless_network_1.EncryptionType.AES;
    }
}
exports.StreamMessage = StreamMessage;
//# sourceMappingURL=StreamMessage.js.map