import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
import { Transform } from 'node:stream';
import { MAX_SIZE } from './config.js';
import { checkLevel, createModule } from './common.js';
const nodeRequire = createRequire(import.meta.url);
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), './../');
const bindings = nodeRequire('node-gyp-build')(rootDir);
const coercion = (data) => {
    if (Buffer.isBuffer(data))
        return data;
    if (ArrayBuffer.isView(data))
        return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
    return Buffer.from(data, 0, data.byteLength);
};
export const { compress, decompress } = createModule({
    coercion,
    compress: (data, level) => bindings.compress(data, level),
    decompress: (data) => bindings.decompress(data, MAX_SIZE),
});
/** NodeJs Transform stream Compressor */
export class Compressor extends Transform {
    constructor(level) {
        super({ objectMode: false });
        this._level = checkLevel(level);
    }
    /** @inheritdoc */
    _construct(callback) {
        try {
            this._binding = new bindings.Compressor(this._level);
            callback();
        }
        catch (ex) {
            callback(ex);
        }
    }
    /** @inheritdoc */
    _transform(chunk, encoding, callback) {
        try {
            if (this._binding == null)
                throw new Error(`Compressor is destroyed`);
            this._binding.data(chunk, (data) => this.push(data));
            callback();
        }
        catch (ex) {
            callback(ex);
        }
    }
    /** @inheritdoc */
    _flush(callback) {
        try {
            if (this._binding == null)
                throw new Error(`Compressor is destroyed`);
            this._binding.end((data) => this.push(data));
            callback();
        }
        catch (ex) {
            callback(ex);
        }
    }
    /** @inheritdoc */
    _destroy(error, callback) {
        try {
            this._binding = undefined;
            callback(error);
        }
        catch (ex) {
            callback(ex);
        }
    }
}
/** NodeJs Transform stream Decompressor */
export class Decompressor extends Transform {
    constructor() {
        super({ objectMode: false });
    }
    /** @inheritdoc */
    _construct(callback) {
        try {
            this._binding = new bindings.Decompressor();
            callback();
        }
        catch (ex) {
            callback(ex);
        }
    }
    /** @inheritdoc */
    _transform(chunk, encoding, callback) {
        try {
            if (this._binding == null)
                throw new Error(`Decompressor is destroyed`);
            this._binding.data(chunk, (data) => this.push(data));
            callback();
        }
        catch (ex) {
            callback(ex);
        }
    }
    /** @inheritdoc */
    _flush(callback) {
        try {
            if (this._binding == null)
                throw new Error(`Decompressor is destroyed`);
            this._binding.end((data) => this.push(data));
            callback();
        }
        catch (ex) {
            callback(ex);
        }
    }
    /** @inheritdoc */
    _destroy(error, callback) {
        try {
            this._binding = undefined;
            callback(error);
        }
        catch (ex) {
            callback(ex);
        }
    }
}
export const ZSTD_VERSION = () => bindings.version;
export const TYPE = 'napi';
// For testing purpose
export const _NapiBindings = bindings;
export default null;
//# sourceMappingURL=napi.js.map