/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java.util.zip;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import libcore.io.Streams;

/**
 * This class provides an implementation of {@code FilterOutputStream} that
 * compresses data using the <i>DEFLATE</i> algorithm. Basically it wraps the
 * {@code Deflater} class and takes care of the buffering.
 *
 * @see Deflater
 */
public class DeflaterOutputStream extends FilterOutputStream {
    static final int BUF_SIZE = 512;

    /**
     * The buffer for the data to be written to.
     */
    protected byte[] buf;

    /**
     * The deflater used.
     */
    protected Deflater def;

    boolean done = false;

    private final boolean syncFlush;

    /**
     * This constructor lets you pass the {@code Deflater} specifying the
     * compression algorithm.
     *
     * @param os
     *            is the {@code OutputStream} where to write the compressed data
     *            to.
     * @param def
     *            is the specific {@code Deflater} that is used to compress
     *            data.
     */
    public DeflaterOutputStream(OutputStream os, Deflater def) {
        this(os, def, BUF_SIZE, false);
    }

    /**
     * This is the most basic constructor. You only need to pass the {@code
     * OutputStream} to which the compressed data shall be written to. The
     * default settings for the {@code Deflater} and internal buffer are used.
     * In particular the {@code Deflater} produces a ZLIB header in the output
     * stream.
     *
     * @param os
     *            is the OutputStream where to write the compressed data to.
     */
    public DeflaterOutputStream(OutputStream os) {
        this(os, new Deflater(), BUF_SIZE, false);
    }

    /**
     * This constructor lets you specify both the compression algorithm as well
     * as the internal buffer size to be used.
     *
     * @param os
     *            is the {@code OutputStream} where to write the compressed data
     *            to.
     * @param def
     *            is the specific {@code Deflater} that will be used to compress
     *            data.
     * @param bufferSize
     *            is the size to be used for the internal buffer.
     */
    public DeflaterOutputStream(OutputStream os, Deflater def, int bufferSize) {
        this(os, def, bufferSize, false);
    }

    /**
     * @hide
     * @since 1.7
     */
    public DeflaterOutputStream(OutputStream os, boolean syncFlush) {
        this(os, new Deflater(), BUF_SIZE, syncFlush);
    }

    /**
     * @hide
     * @since 1.7
     */
    public DeflaterOutputStream(OutputStream os, Deflater def, boolean syncFlush) {
        this(os, def, BUF_SIZE, syncFlush);
    }

    /**
     * @hide
     * @since 1.7
     */
    public DeflaterOutputStream(OutputStream os, Deflater def, int bufferSize, boolean syncFlush) {
        super(os);
        if (os == null) {
            throw new NullPointerException("os == null");
        } else if (def == null) {
            throw new NullPointerException("def == null");
        }
        if (bufferSize <= 0) {
            throw new IllegalArgumentException("bufferSize <= 0: " + bufferSize);
        }
        this.def = def;
        this.syncFlush = syncFlush;
        buf = new byte[bufferSize];
    }

    /**
     * Compress the data in the input buffer and write it to the underlying
     * stream.
     *
     * @throws IOException
     *             If an error occurs during deflation.
     */
    protected void deflate() throws IOException {
        int byteCount;
        while ((byteCount = def.deflate(buf)) != 0) {
            out.write(buf, 0, byteCount);
        }
    }

    /**
     * Writes any unwritten compressed data to the underlying stream, the closes
     * all underlying streams. This stream can no longer be used after close()
     * has been called.
     *
     * @throws IOException
     *             If an error occurs while closing the data compression
     *             process.
     */
    @Override
    public void close() throws IOException {
        // everything closed here should also be closed in ZipOutputStream.close()
        if (!def.finished()) {
            finish();
        }
        def.end();
        out.close();
    }

    /**
     * Writes any unwritten data to the underlying stream. Does not close the
     * stream.
     *
     * @throws IOException
     *             If an error occurs.
     */
    public void finish() throws IOException {
        if (done) {
            return;
        }
        def.finish();
        while (!def.finished()) {
            int byteCount = def.deflate(buf);
            out.write(buf, 0, byteCount);
        }
        done = true;
    }

    @Override public void write(int i) throws IOException {
        Streams.writeSingleByte(this, i);
    }

    /**
     * Compresses {@code byteCount} bytes of data from {@code buf} starting at
     * {@code offset} and writes it to the underlying stream.
     * @throws IOException
     *             If an error occurs during writing.
     */
    @Override public void write(byte[] buffer, int offset, int byteCount) throws IOException {
        if (done) {
            throw new IOException("attempt to write after finish");
        }
        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
        if (!def.needsInput()) {
            throw new IOException();
        }
        def.setInput(buffer, offset, byteCount);
        deflate();
    }

    /**
     * Flushes the underlying stream. This flushes only the bytes that can be
     * compressed at the highest level.
     *
     * <p>For deflater output streams constructed with Java 7's
     * {@code syncFlush} parameter set to true (not yet available on Android),
     * this first flushes all outstanding data so that it may be immediately
     * read by its recipient. Doing so may degrade compression.
     */
    @Override public void flush() throws IOException {
        if (syncFlush) {
            int byteCount;
            while ((byteCount = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH)) != 0) {
                out.write(buf, 0, byteCount);
            }
        }
        out.flush();
    }
}
