// 
// Decompiled by Procyon v0.6.0
// 

package com.github.luben.zstd;

import com.github.luben.zstd.util.Native;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.io.FilterOutputStream;

public class ZstdOutputStreamNoFinalizer extends FilterOutputStream
{
    private final long stream;
    private long srcPos;
    private long dstPos;
    private final BufferPool bufferPool;
    private final ByteBuffer dstByteBuffer;
    private final byte[] dst;
    private boolean isClosed;
    private static final int dstSize;
    private boolean closeFrameOnFlush;
    private boolean frameClosed;
    private boolean frameStarted;
    
    public static native long recommendedCOutSize();
    
    private static native long createCStream();
    
    private static native int freeCStream(final long p0);
    
    private native int resetCStream(final long p0);
    
    private native int compressStream(final long p0, final byte[] p1, final int p2, final byte[] p3, final int p4);
    
    private native int flushStream(final long p0, final byte[] p1, final int p2);
    
    private native int endStream(final long p0, final byte[] p1, final int p2);
    
    public ZstdOutputStreamNoFinalizer(final OutputStream outputStream, final int n) throws IOException {
        this(outputStream, NoPool.INSTANCE);
        Zstd.setCompressionLevel(this.stream, n);
    }
    
    public ZstdOutputStreamNoFinalizer(final OutputStream outputStream) throws IOException {
        this(outputStream, NoPool.INSTANCE);
    }
    
    public ZstdOutputStreamNoFinalizer(final OutputStream outputStream, final BufferPool bufferPool, final int n) throws IOException {
        this(outputStream, bufferPool);
        Zstd.setCompressionLevel(this.stream, n);
    }
    
    public ZstdOutputStreamNoFinalizer(final OutputStream out, final BufferPool bufferPool) throws IOException {
        super(out);
        this.srcPos = 0L;
        this.dstPos = 0L;
        this.isClosed = false;
        this.closeFrameOnFlush = false;
        this.frameClosed = true;
        this.frameStarted = false;
        this.stream = createCStream();
        this.bufferPool = bufferPool;
        this.dstByteBuffer = Zstd.getArrayBackedBuffer(bufferPool, ZstdOutputStreamNoFinalizer.dstSize);
        this.dst = this.dstByteBuffer.array();
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setChecksum(final boolean b) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionChecksums = Zstd.setCompressionChecksums(this.stream, b);
        if (Zstd.isError(setCompressionChecksums)) {
            throw new ZstdIOException(setCompressionChecksums);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setLevel(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionLevel = Zstd.setCompressionLevel(this.stream, n);
        if (Zstd.isError(setCompressionLevel)) {
            throw new ZstdIOException(setCompressionLevel);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setLong(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionLong = Zstd.setCompressionLong(this.stream, n);
        if (Zstd.isError(setCompressionLong)) {
            throw new ZstdIOException(setCompressionLong);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setWorkers(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionWorkers = Zstd.setCompressionWorkers(this.stream, n);
        if (Zstd.isError(setCompressionWorkers)) {
            throw new ZstdIOException(setCompressionWorkers);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setOverlapLog(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionOverlapLog = Zstd.setCompressionOverlapLog(this.stream, n);
        if (Zstd.isError(setCompressionOverlapLog)) {
            throw new ZstdIOException(setCompressionOverlapLog);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setJobSize(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionJobSize = Zstd.setCompressionJobSize(this.stream, n);
        if (Zstd.isError(setCompressionJobSize)) {
            throw new ZstdIOException(setCompressionJobSize);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setTargetLength(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionTargetLength = Zstd.setCompressionTargetLength(this.stream, n);
        if (Zstd.isError(setCompressionTargetLength)) {
            throw new ZstdIOException(setCompressionTargetLength);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setMinMatch(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionMinMatch = Zstd.setCompressionMinMatch(this.stream, n);
        if (Zstd.isError(setCompressionMinMatch)) {
            throw new ZstdIOException(setCompressionMinMatch);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setSearchLog(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionSearchLog = Zstd.setCompressionSearchLog(this.stream, n);
        if (Zstd.isError(setCompressionSearchLog)) {
            throw new ZstdIOException(setCompressionSearchLog);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setChainLog(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionChainLog = Zstd.setCompressionChainLog(this.stream, n);
        if (Zstd.isError(setCompressionChainLog)) {
            throw new ZstdIOException(setCompressionChainLog);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setHashLog(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionHashLog = Zstd.setCompressionHashLog(this.stream, n);
        if (Zstd.isError(setCompressionHashLog)) {
            throw new ZstdIOException(setCompressionHashLog);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setWindowLog(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionWindowLog = Zstd.setCompressionWindowLog(this.stream, n);
        if (Zstd.isError(setCompressionWindowLog)) {
            throw new ZstdIOException(setCompressionWindowLog);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setStrategy(final int n) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int setCompressionStrategy = Zstd.setCompressionStrategy(this.stream, n);
        if (Zstd.isError(setCompressionStrategy)) {
            throw new ZstdIOException(setCompressionStrategy);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setCloseFrameOnFlush(final boolean closeFrameOnFlush) {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        this.closeFrameOnFlush = closeFrameOnFlush;
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setDict(final byte[] array) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int loadDictCompress = Zstd.loadDictCompress(this.stream, array, array.length);
        if (Zstd.isError(loadDictCompress)) {
            throw new ZstdIOException(loadDictCompress);
        }
        return this;
    }
    
    public synchronized ZstdOutputStreamNoFinalizer setDict(final ZstdDictCompress zstdDictCompress) throws IOException {
        if (!this.frameClosed) {
            throw new IllegalStateException("Change of parameter on initialized stream");
        }
        final int loadFastDictCompress = Zstd.loadFastDictCompress(this.stream, zstdDictCompress);
        if (Zstd.isError(loadFastDictCompress)) {
            throw new ZstdIOException(loadFastDictCompress);
        }
        return this;
    }
    
    @Override
    public synchronized void write(final byte[] array, final int n, final int n2) throws IOException {
        if (this.isClosed) {
            throw new IOException("StreamClosed");
        }
        if (this.frameClosed) {
            final int resetCStream = this.resetCStream(this.stream);
            if (Zstd.isError(resetCStream)) {
                throw new ZstdIOException(resetCStream);
            }
            this.frameClosed = false;
            this.frameStarted = true;
        }
        final int n3 = n + n2;
        this.srcPos = n;
        while (this.srcPos < n3) {
            final int compressStream = this.compressStream(this.stream, this.dst, ZstdOutputStreamNoFinalizer.dstSize, array, n3);
            if (Zstd.isError(compressStream)) {
                throw new ZstdIOException(compressStream);
            }
            if (this.dstPos <= 0L) {
                continue;
            }
            this.out.write(this.dst, 0, (int)this.dstPos);
        }
    }
    
    @Override
    public void write(final int n) throws IOException {
        this.write(new byte[] { (byte)n }, 0, 1);
    }
    
    @Override
    public synchronized void flush() throws IOException {
        if (this.isClosed) {
            throw new IOException("StreamClosed");
        }
        if (!this.frameClosed) {
            if (this.closeFrameOnFlush) {
                int i;
                do {
                    i = this.endStream(this.stream, this.dst, ZstdOutputStreamNoFinalizer.dstSize);
                    if (Zstd.isError(i)) {
                        throw new ZstdIOException(i);
                    }
                    this.out.write(this.dst, 0, (int)this.dstPos);
                } while (i > 0);
                this.frameClosed = true;
            }
            else {
                int j;
                do {
                    j = this.flushStream(this.stream, this.dst, ZstdOutputStreamNoFinalizer.dstSize);
                    if (Zstd.isError(j)) {
                        throw new ZstdIOException(j);
                    }
                    this.out.write(this.dst, 0, (int)this.dstPos);
                } while (j > 0);
            }
            this.out.flush();
        }
    }
    
    @Override
    public synchronized void close() throws IOException {
        this.close(true);
    }
    
    public synchronized void closeWithoutClosingParentStream() throws IOException {
        this.close(false);
    }
    
    private void close(final boolean b) throws IOException {
        if (this.isClosed) {
            return;
        }
        try {
            if (!this.frameStarted) {
                final int resetCStream = this.resetCStream(this.stream);
                if (Zstd.isError(resetCStream)) {
                    throw new ZstdIOException(resetCStream);
                }
                this.frameClosed = false;
            }
            if (!this.frameClosed) {
                int i;
                do {
                    i = this.endStream(this.stream, this.dst, ZstdOutputStreamNoFinalizer.dstSize);
                    if (Zstd.isError(i)) {
                        throw new ZstdIOException(i);
                    }
                    this.out.write(this.dst, 0, (int)this.dstPos);
                } while (i > 0);
            }
            if (b) {
                this.out.close();
            }
        }
        finally {
            this.isClosed = true;
            this.bufferPool.release(this.dstByteBuffer);
            freeCStream(this.stream);
        }
    }
    
    static {
        Native.load();
        dstSize = (int)recommendedCOutSize();
    }
}
