/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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 android.util;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * An OutputStream that does Base64 encoding on the data written to
 * it, writing the resulting data to another OutputStream.
 */
public class Base64OutputStream extends FilterOutputStream {
    private final Base64.Coder coder;
    private final int flags;

    private byte[] buffer = null;
    private int bpos = 0;

    private static byte[] EMPTY = new byte[0];

    /**
     * Performs Base64 encoding on the data written to the stream,
     * writing the encoded data to another OutputStream.
     *
     * @param out the OutputStream to write the encoded data to
     * @param flags bit flags for controlling the encoder; see the
     *        constants in {@link Base64}
     */
    public Base64OutputStream(OutputStream out, int flags) {
        this(out, flags, true);
    }

    /**
     * Performs Base64 encoding or decoding on the data written to the
     * stream, writing the encoded/decoded data to another
     * OutputStream.
     *
     * @param out the OutputStream to write the encoded data to
     * @param flags bit flags for controlling the encoder; see the
     *        constants in {@link Base64}
     * @param encode true to encode, false to decode
     *
     * @hide
     */
    public Base64OutputStream(OutputStream out, int flags, boolean encode) {
        super(out);
        this.flags = flags;
        if (encode) {
            coder = new Base64.Encoder(flags, null);
        } else {
            coder = new Base64.Decoder(flags, null);
        }
    }

    public void write(int b) throws IOException {
        // To avoid invoking the encoder/decoder routines for single
        // bytes, we buffer up calls to write(int) in an internal
        // byte array to transform them into writes of decently-sized
        // arrays.

        if (buffer == null) {
            buffer = new byte[1024];
        }
        if (bpos >= buffer.length) {
            // internal buffer full; write it out.
            internalWrite(buffer, 0, bpos, false);
            bpos = 0;
        }
        buffer[bpos++] = (byte) b;
    }

    /**
     * Flush any buffered data from calls to write(int).  Needed
     * before doing a write(byte[], int, int) or a close().
     */
    private void flushBuffer() throws IOException {
        if (bpos > 0) {
            internalWrite(buffer, 0, bpos, false);
            bpos = 0;
        }
    }

    public void write(byte[] b, int off, int len) throws IOException {
        if (len <= 0) return;
        flushBuffer();
        internalWrite(b, off, len, false);
    }

    public void close() throws IOException {
        IOException thrown = null;
        try {
            flushBuffer();
            internalWrite(EMPTY, 0, 0, true);
        } catch (IOException e) {
            thrown = e;
        }

        try {
            if ((flags & Base64.NO_CLOSE) == 0) {
                out.close();
            } else {
                out.flush();
            }
        } catch (IOException e) {
            if (thrown == null) {
                thrown = e;
            } else {
                thrown.addSuppressed(e);
            }
        }

        if (thrown != null) {
            throw thrown;
        }
    }

    /**
     * Write the given bytes to the encoder/decoder.
     *
     * @param finish true if this is the last batch of input, to cause
     *        encoder/decoder state to be finalized.
     */
    private void internalWrite(byte[] b, int off, int len, boolean finish) throws IOException {
        coder.output = embiggen(coder.output, coder.maxOutputSize(len));
        if (!coder.process(b, off, len, finish)) {
            throw new Base64DataException("bad base-64");
        }
        out.write(coder.output, 0, coder.op);
    }

    /**
     * If b.length is at least len, return b.  Otherwise return a new
     * byte array of length len.
     */
    private byte[] embiggen(byte[] b, int len) {
        if (b == null || b.length < len) {
            return new byte[len];
        } else {
            return b;
        }
    }
}
