"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeBsonStringifiers = void 0;
exports.makePrintableBson = makePrintableBson;
const inspectCustom = Symbol.for('nodejs.util.inspect.custom');
let coreUtilInspect;
function inspectTypedArray(obj, options) {
    try {
        coreUtilInspect ?? (coreUtilInspect = require('util').inspect);
        return coreUtilInspect(obj, {
            ...options,
            maxArrayLength: coreUtilInspect.defaultOptions.maxArrayLength,
        });
    }
    catch {
        const arr = Array.from(obj);
        if (arr.length > 100) {
            return `[${arr.slice(0, 100).join(', ')}, ... ${arr.length - 100} more items]`;
        }
        return `[${arr.join(', ')}]`;
    }
}
function removeNewFromInspectResult(str) {
    return str.replace(/^(\s*)(new )/, '$1');
}
function removeTypedArrayPrefixFromInspectResult(str) {
    return str.replace(/^\s*\S+\s*\(\d+\)\s*/, '');
}
function makeClasslessInspect(cls) {
    const originalInspect = cls.prototype.inspect;
    return function (...args) {
        return removeNewFromInspectResult(originalInspect.apply(this, args));
    };
}
const makeBinaryVectorInspect = (bsonLibrary) => {
    return function (depth, options) {
        const binaryInspect = makeClasslessInspect(bsonLibrary.Binary);
        switch (this.buffer[0]) {
            case bsonLibrary.Binary.VECTOR_TYPE.Int8:
                return `Binary.fromInt8Array(new Int8Array(${removeTypedArrayPrefixFromInspectResult(inspectTypedArray(this.toInt8Array(), {
                    depth,
                    ...options,
                }))}))`;
            case bsonLibrary.Binary.VECTOR_TYPE.Float32:
                return `Binary.fromFloat32Array(new Float32Array(${removeTypedArrayPrefixFromInspectResult(inspectTypedArray(this.toFloat32Array(), {
                    depth,
                    ...options,
                }))}))`;
            case bsonLibrary.Binary.VECTOR_TYPE.PackedBit: {
                const paddingInfo = this.buffer[1] === 0 ? '' : `, ${this.buffer[1]}`;
                return `Binary.fromPackedBits(new Uint8Array(${removeTypedArrayPrefixFromInspectResult(inspectTypedArray(this.toPackedBits(), {
                    depth,
                    ...options,
                }))})${paddingInfo})`;
            }
            default:
                return binaryInspect.call(this, depth, options);
        }
    };
};
const makeBsonStringifiers = (bsonLibrary) => {
    const binaryVectorInspect = makeBinaryVectorInspect(bsonLibrary);
    const binaryInspect = makeClasslessInspect(bsonLibrary.Binary);
    return {
        ObjectId: makeClasslessInspect(bsonLibrary.ObjectId),
        ObjectID: makeClasslessInspect(bsonLibrary.ObjectId),
        DBRef: makeClasslessInspect(bsonLibrary.DBRef),
        MaxKey: makeClasslessInspect(bsonLibrary.MaxKey),
        MinKey: makeClasslessInspect(bsonLibrary.MinKey),
        Timestamp: makeClasslessInspect(bsonLibrary.Timestamp),
        BSONSymbol: makeClasslessInspect(bsonLibrary.BSONSymbol),
        Code: makeClasslessInspect(bsonLibrary.Code),
        Decimal128: makeClasslessInspect(bsonLibrary.Decimal128),
        Int32: makeClasslessInspect(bsonLibrary.Int32),
        Long: makeClasslessInspect(bsonLibrary.Long),
        Double: makeClasslessInspect(bsonLibrary.Double),
        BSONRegExp: makeClasslessInspect(bsonLibrary.BSONRegExp),
        Binary: function (...args) {
            const hexString = this.toString('hex');
            switch (this.sub_type) {
                case bsonLibrary.Binary.SUBTYPE_VECTOR:
                    return binaryVectorInspect.apply(this, args);
                case bsonLibrary.Binary.SUBTYPE_MD5:
                    return `MD5('${hexString}')`;
                case bsonLibrary.Binary.SUBTYPE_UUID:
                    if (hexString.length === 32) {
                        const asUUID = /^(.{8})(.{4})(.{4})(.{4})(.{12})$/
                            .exec(hexString)
                            .slice(1, 6)
                            .join('-');
                        return `UUID('${asUUID}')`;
                    }
                default:
                    return binaryInspect.apply(this, args);
            }
        },
    };
};
exports.makeBsonStringifiers = makeBsonStringifiers;
function makePrintableBson(bsonLibrary) {
    for (const [key, stringifier] of Object.entries((0, exports.makeBsonStringifiers)(bsonLibrary))) {
        if (!(key in bsonLibrary)) {
            continue;
        }
        const cls = bsonLibrary[key];
        for (const key of [inspectCustom, 'inspect']) {
            cls.prototype[key] = stringifier;
        }
    }
}
//# sourceMappingURL=printable-bson.js.map