"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.estimateBinarySizeOfObject = exports.requestErrorHandler = exports.verificationDataSplitter = exports.verificationDataCombiner = exports.getStreamWithTypeCheck = exports.requestSerializer = exports.responseDeserializer = exports.responseSerializer = void 0;
const logger_1 = require("../logger");
const nestedCounters_1 = require("../utils/nestedCounters");
const VectorBufferStream_1 = require("../utils/serialization/VectorBufferStream");
const WrappedReq_1 = require("./WrappedReq");
const WrappedResp_1 = require("./WrappedResp");
const TypeIdentifierEnum_1 = require("./enum/TypeIdentifierEnum");
const ResponseError_1 = require("./ResponseError");
const responseSerializer = (data, serializerFunc) => {
    const bufferInitialSize = estimateBinarySizeOfObject(data);
    const serializedPayload = new VectorBufferStream_1.VectorBufferStream(bufferInitialSize);
    serializerFunc(serializedPayload, data, true);
    const resp = {
        payload: serializedPayload.getBuffer(),
    };
    const wrappedRespStream = new VectorBufferStream_1.VectorBufferStream(3 + resp.payload.length);
    (0, WrappedResp_1.serializeWrappedResp)(wrappedRespStream, resp, true);
    return wrappedRespStream;
};
exports.responseSerializer = responseSerializer;
const responseDeserializer = (data, deserializerFunc) => {
    data.position = 0;
    const responseType = data.readUInt16();
    if (responseType !== TypeIdentifierEnum_1.TypeIdentifierEnum.cWrappedResp) {
        throw new Error(`Invalid response stream: ${responseType}`);
    }
    const wrappedResp = (0, WrappedResp_1.deserializeWrappedResp)(data);
    const payloadStream = VectorBufferStream_1.VectorBufferStream.fromBuffer(wrappedResp.payload);
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const payloadType = payloadStream.readUInt16();
    if (payloadType === TypeIdentifierEnum_1.TypeIdentifierEnum.cResponseError) {
        throw (0, ResponseError_1.deserializeResponseError)(payloadStream);
    }
    return deserializerFunc(payloadStream);
};
exports.responseDeserializer = responseDeserializer;
const requestSerializer = (data, serializerFunc) => {
    const bufferInitialSize = estimateBinarySizeOfObject(data);
    const serializedPayload = new VectorBufferStream_1.VectorBufferStream(bufferInitialSize);
    serializerFunc(serializedPayload, data, true);
    const req = {
        payload: serializedPayload.getBuffer(),
    };
    const wrappedReqStream = new VectorBufferStream_1.VectorBufferStream(3 + req.payload.length);
    (0, WrappedReq_1.serializeWrappedReq)(wrappedReqStream, req, true);
    return wrappedReqStream;
};
exports.requestSerializer = requestSerializer;
// this function pop the first 2 bytes of the stream and check if it matches the typeId
const getStreamWithTypeCheck = (payload, typeId, customErrorLog) => {
    const requestStream = VectorBufferStream_1.VectorBufferStream.fromBuffer(payload);
    const requestType = requestStream.readUInt16();
    if (requestType !== typeId) {
        /* prettier-ignore */ console.log(`Invalid request stream: expected: ${typeId} actual: ${requestType}. ${customErrorLog ? customErrorLog : ''}`);
        return null;
    }
    return requestStream;
};
exports.getStreamWithTypeCheck = getStreamWithTypeCheck;
const verificationDataCombiner = (...args) => {
    return args.join(':');
};
exports.verificationDataCombiner = verificationDataCombiner;
const verificationDataSplitter = (data) => {
    return data.split(':');
};
exports.verificationDataSplitter = verificationDataSplitter;
const requestErrorHandler = (apiRoute, errorType, header, opts) => {
    let logMessage = `route: ${apiRoute}, error_type: ${errorType}, sender_id: ${header.sender_id}, tracker_id: ${header.tracker_id}, verification_data: ${header.verification_data}`;
    if (opts?.customErrorLog) {
        logMessage += `, custom_log: ${opts.customErrorLog}`;
    }
    /* prettier-ignore */ if (logger_1.logFlags.error && logger_1.logFlags.console)
        console.log(logMessage);
    let counter = `${apiRoute}_${errorType}`;
    if (opts?.customCounterSuffix) {
        counter += `_${opts.customCounterSuffix}`;
    }
    nestedCounters_1.nestedCountersInstance.countEvent('internal', counter);
};
exports.requestErrorHandler = requestErrorHandler;
function estimateBinarySizeOfObject(obj) {
    const sizes = {
        number: 8,
        boolean: 1,
        string: (str) => 2 + str.length * 2, // 2 bytes for length + string length * 2 bytes
    };
    const calculateSize = (item) => {
        const type = typeof item;
        if (type === 'number') {
            return sizes.number;
        }
        else if (type === 'boolean') {
            return sizes.boolean;
        }
        else if (type === 'string') {
            return sizes.string(item);
        }
        else if (Array.isArray(item)) {
            if (item.length === 0) {
                return 0;
            }
            return 2 + item.length * calculateSize(item[0]);
        }
        else if (item && type === 'object') {
            // eslint-disable-next-line security/detect-object-injection
            return Object.keys(item).reduce((acc, key) => acc + calculateSize(item[key]), 0);
        }
        return 0;
    };
    return calculateSize(obj);
}
exports.estimateBinarySizeOfObject = estimateBinarySizeOfObject;
//# sourceMappingURL=Helpers.js.map