/*
 * BlockOutputStream
 *
 * Author: Lasse Collin <lasse.collin@tukaani.org>
 *
 * This file has been put into the public domain.
 * You can do whatever you want with this file.
 */

package org.tukaani.xz;

import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.tukaani.xz.common.EncoderUtil;
import org.tukaani.xz.check.Check;

class BlockOutputStream extends FinishableOutputStream {
    private final OutputStream out;
    private final CountingOutputStream outCounted;
    private FinishableOutputStream filterChain;
    private final Check check;

    private final int headerSize;
    private final long compressedSizeLimit;
    private long uncompressedSize = 0;

    private final byte[] tempBuf = new byte[1];

    public BlockOutputStream(OutputStream out, FilterEncoder[] filters,
                             Check check) throws IOException {
        this.out = out;
        this.check = check;

        // Initialize the filter chain.
        outCounted = new CountingOutputStream(out);
        filterChain = outCounted;
        for (int i = filters.length - 1; i >= 0; --i)
            filterChain = filters[i].getOutputStream(filterChain);

        // Prepare to encode the Block Header field.
        ByteArrayOutputStream bufStream = new ByteArrayOutputStream();

        // Write a dummy Block Header Size field. The real value is written
        // once everything else except CRC32 has been written.
        bufStream.write(0x00);

        // Write Block Flags. Storing Compressed Size or Uncompressed Size
        // isn't supported for now.
        bufStream.write(filters.length - 1);

        // List of Filter Flags
        for (int i = 0; i < filters.length; ++i) {
            EncoderUtil.encodeVLI(bufStream, filters[i].getFilterID());
            byte[] filterProps = filters[i].getFilterProps();
            EncoderUtil.encodeVLI(bufStream, filterProps.length);
            bufStream.write(filterProps);
        }

        // Header Padding
        while ((bufStream.size() & 3) != 0)
            bufStream.write(0x00);

        byte[] buf = bufStream.toByteArray();

        // Total size of the Block Header: Take the size of the CRC32 field
        // into account.
        headerSize = buf.length + 4;

        // This is just a sanity check.
        if (headerSize > EncoderUtil.BLOCK_HEADER_SIZE_MAX)
            throw new UnsupportedOptionsException();

        // Block Header Size
        buf[0] = (byte)(buf.length / 4);

        // Write the Block Header field to the output stream.
        out.write(buf);
        EncoderUtil.writeCRC32(out, buf);

        // Calculate the maximum allowed size of the Compressed Data field.
        // It is hard to exceed it so this is mostly to be pedantic.
        compressedSizeLimit = (EncoderUtil.VLI_MAX & ~3)
                              - headerSize - check.getSize();
    }

    public void write(int b) throws IOException {
        tempBuf[0] = (byte)b;
        write(tempBuf, 0, 1);
    }

    public void write(byte[] buf, int off, int len) throws IOException {
        filterChain.write(buf, off, len);
        check.update(buf, off, len);
        uncompressedSize += len;
        validate();
    }

    public void flush() throws IOException {
        filterChain.flush();
        validate();
    }

    public void finish() throws IOException {
        // Finish the Compressed Data field.
        filterChain.finish();
        validate();

        // Block Padding
        for (long i = outCounted.getSize(); (i & 3) != 0; ++i)
            out.write(0x00);

        // Check
        out.write(check.finish());
    }

    private void validate() throws IOException {
        long compressedSize = outCounted.getSize();

        // It is very hard to trigger this exception.
        // This is just to be pedantic.
        if (compressedSize < 0 || compressedSize > compressedSizeLimit
                || uncompressedSize < 0)
            throw new XZIOException("XZ Stream has grown too big");
    }

    public long getUnpaddedSize() {
        return headerSize + outCounted.getSize() + check.getSize();
    }

    public long getUncompressedSize() {
        return uncompressedSize;
    }
}
