/*
 * 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
 */

package com.pullenti.unitext.internal.zip;

// A special stream deflating or compressing the bytes that are
// written to it.  It uses a Deflater to perform actual deflating.<br/>
public class DeflaterOutputStream extends com.pullenti.unisharp.Stream {

    public DeflaterOutputStream(com.pullenti.unisharp.Stream baseOutputStream, Deflater deflater, int bufferSize) {
        super();
        if (deflater == null) 
            deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, false);
        baseOutputStream_ = baseOutputStream;
        buffer_ = new byte[bufferSize];
        deflater_ = deflater;
    }

    public void finish() throws Exception, java.io.IOException, UnsupportedOperationException, java.io.FileNotFoundException, IndexOutOfBoundsException {
        deflater_.finish();
        while (!deflater_.isFinished()) {
            int len = deflater_.deflateEx(buffer_, 0, buffer_.length);
            if (len <= 0) 
                break;
            baseOutputStream_.write(buffer_, 0, len);
        }
        if (!deflater_.isFinished()) 
            throw new Exception("Can't deflate all input?");
        baseOutputStream_.flush();
    }

    public boolean isStreamOwner() {
        return isStreamOwner_;
    }

    public boolean setStreamOwner(boolean value) {
        isStreamOwner_ = value;
        return value;
    }


    public boolean canPatchEntries() {
        return baseOutputStream_.canSeek();
    }


    private String password;

    protected void deflate() throws Exception, java.io.IOException, UnsupportedOperationException {
        while (!deflater_.isNeedingInput()) {
            int deflateCount = deflater_.deflateEx(buffer_, 0, buffer_.length);
            if (deflateCount <= 0) 
                break;
            baseOutputStream_.write(buffer_, 0, deflateCount);
        }
        if (!deflater_.isNeedingInput()) 
            throw new Exception("DeflaterOutputStream can't deflate all input?");
    }

    @Override
    public boolean canRead() {
        return false;
    }


    @Override
    public boolean canSeek() {
        return false;
    }


    @Override
    public boolean canWrite() {
        try {
            return baseOutputStream_.canWrite();
        } catch (Exception ex) {
            return false;
        }
    }


    @Override
    public long length() {
        try {
            return baseOutputStream_.length();
        } catch (Exception ex) {
            return -1L;
        }
    }


    @Override
    public long getPosition() {
        try {
            return baseOutputStream_.getPosition();
        } catch (Exception ex) {
            return 0L;
        }
    }

    @Override
    public long setPosition(long value) {
        return value;
    }


    @Override
    public long seek(long offset, int origin) {
        return 0L;
    }

    @Override
    public void setLength(long value) {
    }

    @Override
    public int read() {
        return -1;
    }

    @Override
    public int read(byte[] buffer, int offset, int count) {
        return -1;
    }

    @Override
    public void flush() throws java.io.IOException {
        try {
            deflater_.flush();
            this.deflate();
            baseOutputStream_.flush();
        } catch (Exception ex) {
            throw new java.io.IOException(ex.getMessage(), ex);
        }
    }

    @Override
    public void close() throws java.io.IOException {
        if (!isClosed_) {
            isClosed_ = true;
            try {
                this.finish();
            } catch (Exception ex) {
                throw new java.io.IOException(ex.getMessage(), ex);
            } finally {
                if (isStreamOwner_) {
                    try {
                        baseOutputStream_.close();
                    } catch (Exception ex) {
                    }
                }
            }
        }
    }

    @Override
    public void write(byte value) throws java.io.IOException {
        byte[] b = new byte[1];
        b[0] = value;
        this.write(b, 0, 1);
    }

    @Override
    public void write(byte[] buffer, int offset, int count) throws java.io.IOException {
        try {
            deflater_.setInputEx(buffer, offset, count);
            this.deflate();
        } catch (Exception ex) {
            throw new java.io.IOException(ex.getMessage(), ex);
        }
    }

    private byte[] buffer_;

    protected Deflater deflater_;

    protected com.pullenti.unisharp.Stream baseOutputStream_;

    private boolean isClosed_;

    private boolean isStreamOwner_ = true;
    public DeflaterOutputStream() {
        super();
    }
}
