/**
 * 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 org.apache.cxf.attachment;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.cxf.common.util.Base64Exception;
import org.apache.cxf.common.util.Base64Utility;

/**
 * An implementation of a FilterInputStream that decodes the
 * stream data in BASE64 encoding format.  This version does the
 * decoding "on the fly" rather than decoding a single block of
 * data.  Since this version is intended for use by the MimeUtilty class,
 * it also handles line breaks in the encoded data.
 */
public class Base64DecoderStream extends FilterInputStream {

    static final String MAIL_BASE64_IGNOREERRORS = "mail.mime.base64.ignoreerrors";

    // number of decodeable units we'll try to process at one time.  We'll attempt to read that much
    // data from the input stream and decode in blocks.
    static final int BUFFERED_UNITS = 2000;

    // can be overridden by a system property.
    protected boolean ignoreErrors;

    // buffer for reading in chars for decoding (which can support larger bulk reads)
    protected char[] encodedChars = new char[BUFFERED_UNITS * 4];
    // a buffer for one decoding unit's worth of data (3 bytes).
    protected byte[] decodedChars;
    // count of characters in the buffer
    protected int decodedCount;
    // index of the next decoded character
    protected int decodedIndex;


    public Base64DecoderStream(InputStream in) {
        super(in);
    }

    /**
     * Test for the existance of decoded characters in our buffer
     * of decoded data.
     *
     * @return True if we currently have buffered characters.
     */
    private boolean dataAvailable() {
        return decodedCount != 0;
    }

    /**
     * Decode a requested number of bytes of data into a buffer.
     *
     * @return true if we were able to obtain more data, false otherwise.
     */
    private boolean decodeStreamData() throws IOException {
        decodedIndex = 0;

        // fill up a data buffer with input data
        int readCharacters = fillEncodedBuffer();

        if (readCharacters > 0) {
            try {
                decodedChars = Base64Utility.decodeChunk(encodedChars, 0, readCharacters);
            } catch (Base64Exception e) {
                throw new IOException(e);
            }
            decodedCount = decodedChars.length;
            return true;
        }
        return false;
    }


    /**
     * Retrieve a single byte from the decoded characters buffer.
     *
     * @return The decoded character or -1 if there was an EOF condition.
     */
    private int getByte() throws IOException {
        if (!dataAvailable() && !decodeStreamData()) {
            return -1;
        }
        decodedCount--;
        // we need to ensure this doesn't get sign extended
        return decodedChars[decodedIndex++] & 0xff;
    }

    private int getBytes(byte[] data, int offset, int length) throws IOException {

        int readCharacters = 0;
        while (length > 0) {
            // need data?  Try to get some
            if (!dataAvailable() && !decodeStreamData()) {
                // if we can't get this, return a count of how much we did get (which may be -1).
                return readCharacters > 0 ? readCharacters : -1;
            }

            // now copy some of the data from the decoded buffer to the target buffer
            int copyCount = Math.min(decodedCount, length);
            System.arraycopy(decodedChars, decodedIndex, data, offset, copyCount);
            decodedIndex += copyCount;
            decodedCount -= copyCount;
            offset += copyCount;
            length -= copyCount;
            readCharacters += copyCount;
        }
        return readCharacters;
    }


    /**
     * Fill our buffer of input characters for decoding from the
     * stream.  This will attempt read a full buffer, but will
     * terminate on an EOF or read error.  This will filter out
     * non-Base64 encoding chars and will only return a valid
     * multiple of 4 number of bytes.
     *
     * @return The count of characters read.
     */
    private int fillEncodedBuffer() throws IOException {
        int readCharacters = 0;

        while (true) {
            // get the next character from the stream
            int ch = in.read();
            // did we hit an EOF condition?
            if (ch == -1) {
                // now check to see if this is normal, or potentially an error
                // if we didn't get characters as a multiple of 4, we may need to complain about this.
                if ((readCharacters % 4) != 0) {
                    throw new IOException("Base64 encoding error, data truncated: " + readCharacters + " "
                                          + new String(encodedChars, 0, readCharacters));
                }
                // return the count.
                return readCharacters;
            } else if (Base64Utility.isValidBase64(ch)) {
                // if this character is valid in a Base64 stream, copy it to the buffer.
                encodedChars[readCharacters++] = (char)ch;
                // if we've filled up the buffer, time to quit.
                if (readCharacters >= encodedChars.length) {
                    return readCharacters;
                }
            }

            // we're filtering out whitespace and CRLF characters, so just ignore these
        }
    }


    // in order to function as a filter, these streams need to override the different
    // read() signature.

    @Override
    public int read() throws IOException {
        return getByte();
    }


    @Override
    public int read(byte [] buffer, int offset, int length) throws IOException {
        return getBytes(buffer, offset, length);
    }

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


    @Override
    public int available() throws IOException {
        return ((in.available() / 4) * 3) + decodedCount;
    }
}
