"use strict";
const zlib = require("zlib");
const stream = require("stream");
const png = require("./index");
const constants = require("./constants");
const CrcStream = require("./crc");
const Filter = require("./filter");
class Packer extends stream.Readable {
    constructor(option) {
        super();
        this._option = option;
        option.deflateChunkSize = option.deflateChunkSize || 32 * 1024;
        option.deflateLevel = option.deflateLevel || 9;
        if (option.deflateStrategy === undefined) {
            option.deflateStrategy = png.EDeflateStrategy.RLE;
        }
        this.readable = true;
    }
    pack(data, width, height) {
        // Signature
        this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
        this.emit("data", this._packIHDR(width, height));
        // filter pixel data
        const filter = new Filter(width, height, 4, data, this._option);
        data = filter.filter();
        // compress it
        const deflate = zlib.createDeflate({
            chunkSize: this._option.deflateChunkSize,
            level: this._option.deflateLevel,
            strategy: this._option.deflateStrategy
        });
        deflate.on("error", this.emit.bind(this, "error"));
        deflate.on("data", (data) => {
            this.emit("data", this._packIDAT(data));
        });
        deflate.on("end", () => {
            this.emit("data", this._packIEND());
            this.emit("end");
        });
        deflate.end(data);
    }
    _read() {
        //todo
    }
    _packChunk(type, data) {
        const len = (data ? data.length : 0);
        const buf = Buffer.alloc(len + 12);
        buf.writeUInt32BE(len, 0);
        buf.writeUInt32BE(type, 4);
        if (data) {
            data.copy(buf, 8);
        }
        buf.writeInt32BE(CrcStream.crc32(buf.slice(4, buf.length - 4)), buf.length - 4);
        return buf;
    }
    _packIHDR(width, height) {
        const buf = Buffer.alloc(13);
        buf.writeUInt32BE(width, 0);
        buf.writeUInt32BE(height, 4);
        buf[8] = 8;
        buf[9] = 6; // colorType
        buf[10] = 0; // compression
        buf[11] = 0; // filter
        buf[12] = 0; // interlace
        return this._packChunk(constants.TYPE_IHDR, buf);
    }
    _packIDAT(data) {
        return this._packChunk(constants.TYPE_IDAT, data);
    }
    _packIEND() {
        return this._packChunk(constants.TYPE_IEND, null);
    }
}
module.exports = Packer;
//# sourceMappingURL=packer.js.map