/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter UniSharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

const Stream = require("./../../../unisharp/Stream");

const Deflater = require("./Deflater");

// A special stream deflating or compressing the bytes that are
// written to it.  It uses a Deflater to perform actual deflating.<br/>
class DeflaterOutputStream extends Stream {
    
    constructor(baseOutputStream, deflater = null, bufferSize = 512) {
        super();
        this.password = null;
        this.buffer_ = null;
        this.deflater_ = null;
        this.baseOutputStream_ = null;
        this.isClosed_ = false;
        this.isStreamOwner_ = true;
        if (deflater === null) 
            deflater = new Deflater();
        this.baseOutputStream_ = baseOutputStream;
        this.buffer_ = new Uint8Array(bufferSize);
        this.deflater_ = deflater;
    }
    
    finish() {
        this.deflater_.finish();
        while (!this.deflater_.isFinished) {
            let len = this.deflater_.deflateEx(this.buffer_, 0, this.buffer_.length);
            if (len <= 0) 
                break;
            this.baseOutputStream_.write(this.buffer_, 0, len);
        }
        if (!this.deflater_.isFinished) 
            throw new Error("Can't deflate all input?");
        this.baseOutputStream_.flush();
    }
    
    get isStreamOwner() {
        return this.isStreamOwner_;
    }
    set isStreamOwner(value) {
        this.isStreamOwner_ = value;
        return value;
    }
    
    get canPatchEntries() {
        return this.baseOutputStream_.canSeek();
    }
    
    deflate() {
        while (!this.deflater_.isNeedingInput) {
            let deflateCount = this.deflater_.deflateEx(this.buffer_, 0, this.buffer_.length);
            if (deflateCount <= 0) 
                break;
            this.baseOutputStream_.write(this.buffer_, 0, deflateCount);
        }
        if (!this.deflater_.isNeedingInput) 
            throw new Error("DeflaterOutputStream can't deflate all input?");
    }
    
    get canRead() {
        return false;
    }
    
    get canSeek() {
        return false;
    }
    
    get canWrite() {
        try {
            return this.baseOutputStream_.canWrite();
        } catch (ex) {
            return false;
        }
    }
    
    get length() {
        try {
            return this.baseOutputStream_.length;
        } catch (ex) {
            return -1;
        }
    }
    
    get position() {
        try {
            return this.baseOutputStream_.position;
        } catch (ex) {
            return 0;
        }
    }
    set position(value) {
        return value;
    }
    
    seek(offset, origin) {
        return 0;
    }
    
    setLength(value) {
        
    }
    
    readByte() {
        return -1;
    }
    
    read(buffer, offset, count) {
        return -1;
    }
    
    flush() {
        try {
            this.deflater_.flush();
            this.deflate();
            this.baseOutputStream_.flush();
        } catch (ex) {
            throw new Error(ex.message, ex);
        }
    }
    
    close() {
        if (!this.isClosed_) {
            this.isClosed_ = true;
            try {
                this.finish();
            } catch (ex) {
                throw new Error(ex.message, ex);
            } finally {
                if (this.isStreamOwner_) {
                    try {
                        this.baseOutputStream_.close();
                    } catch (ex) {
                    }
                }
            }
        }
    }
    
    writeByte(value) {
        let b = new Uint8Array(1);
        b[0] = value;
        this.write(b, 0, 1);
    }
    
    write(buffer, offset, count) {
        try {
            this.deflater_.setInputEx(buffer, offset, count);
            this.deflate();
        } catch (ex) {
            throw new Error(ex.message, ex);
        }
    }
}


module.exports = DeflaterOutputStream