/****************************************************************
 * 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.james.mime4j.io;

import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.MimeIOException;
import org.apache.james.mime4j.util.ByteArrayBuffer;
import org.apache.james.mime4j.util.CharsetUtil;

import java.io.IOException;

/**
 * Stream that constrains itself to a single MIME body part.
 * After the stream ends (i.e. read() returns -1) {@link #isLastPart()}
 * can be used to determine if a final boundary has been seen or not.
 */
public class MimeBoundaryInputStream extends LineReaderInputStream {

    private final byte[] boundary;
    private final boolean strict;

    private boolean eof;
    private int limit;
    private boolean atBoundary;
    private int boundaryLen;
    private boolean lastPart;
    private boolean completed;

    private final BufferedLineReaderInputStream buffer;

    /**
     * Store the first buffer length.
     * Used to distinguish between an empty preamble and
     * no preamble.
     */
    private int initialLength;

    /**
     * Creates a new MimeBoundaryInputStream.
     *
     * @param inbuffer The underlying stream.
     * @param boundary Boundary string (not including leading hyphens).
     * @throws IllegalArgumentException when boundary is too long
     */
    public MimeBoundaryInputStream(
            final BufferedLineReaderInputStream inbuffer,
            final String boundary,
            final boolean strict) throws IOException {
        super(inbuffer);
        int bufferSize = 2 * boundary.length();
        if (bufferSize < 4096) {
            bufferSize = 4096;
        }
        inbuffer.ensureCapacity(bufferSize);
        this.buffer = inbuffer;
        this.eof = false;
        this.limit = -1;
        this.atBoundary = false;
        this.boundaryLen = 0;
        this.lastPart = false;
        this.initialLength = -1;
        this.completed = false;

        this.strict = strict;
        this.boundary = new byte[boundary.length() + 2];
        this.boundary[0] = (byte) '-';
        this.boundary[1] = (byte) '-';
        for (int i = 0; i < boundary.length(); i++) {
            byte ch = (byte) boundary.charAt(i);
            this.boundary[i + 2] = ch;
        }

        fillBuffer();
    }

    /**
     * Creates a new MimeBoundaryInputStream.
     *
     * @param inbuffer The underlying stream.
     * @param boundary Boundary string (not including leading hyphens).
     * @throws IllegalArgumentException when boundary is too long
     */
    public MimeBoundaryInputStream(
            final BufferedLineReaderInputStream inbuffer,
            final String boundary) throws IOException {
        this(inbuffer, boundary, false);
    }

    /**
     * Closes the underlying stream.
     *
     * @throws IOException on I/O errors.
     */
    @Override
    public void close() throws IOException {
    }

    /**
     * @see java.io.InputStream#markSupported()
     */
    @Override
    public boolean markSupported() {
        return false;
    }

    public boolean readAllowed() throws IOException {
        if (completed) {
            return false;
        }
        if (endOfStream() && !hasData()) {
            skipBoundary();
            verifyEndOfStream();
            return false;
        }
        return true;
    }

    /**
     * @see java.io.InputStream#read()
     */
    @Override
    public int read() throws IOException {
        for (;;) {
            if (!readAllowed()) return -1;
            if (hasData()) {
                return buffer.read();
            }
            fillBuffer();
        }
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        for (;;) {
            if (!readAllowed()) return -1;
            if (hasData()) {
                int chunk = Math.min(len, limit - buffer.pos());
                return buffer.read(b, off, chunk);
            }
            fillBuffer();
        }
    }

    @Override
    public int readLine(final ByteArrayBuffer dst) throws IOException {
        if (dst == null) {
            throw new IllegalArgumentException("Destination buffer may not be null");
        }
        if (!readAllowed()) return -1;

        int total = 0;
        boolean found = false;
        int bytesRead = 0;
        while (!found) {
            if (!hasData()) {
                bytesRead = fillBuffer();
                if (endOfStream() && !hasData()) {
                    skipBoundary();
                    verifyEndOfStream();
                    bytesRead = -1;
                    break;
                }
            }
            int len = this.limit - this.buffer.pos();
            int i = this.buffer.indexOf((byte)'\n', this.buffer.pos(), len);
            int chunk;
            if (i != -1) {
                found = true;
                chunk = i + 1 - this.buffer.pos();
            } else {
                chunk = len;
            }
            if (chunk > 0) {
                dst.append(this.buffer.buf(), this.buffer.pos(), chunk);
                this.buffer.skip(chunk);
                total += chunk;
            }
        }
        if (total == 0 && bytesRead == -1) {
            return -1;
        } else {
            return total;
        }
    }

    private void verifyEndOfStream() throws IOException {
        if (strict && eof && !atBoundary) {
            throw new MimeIOException(new MimeException("Unexpected end of stream"));
        }
    }

    private boolean endOfStream() {
        return eof || atBoundary;
    }

    private boolean hasData() {
        return limit > buffer.pos() && limit <= buffer.limit();
    }

    private int fillBuffer() throws IOException {
        if (eof) {
            return -1;
        }
        int bytesRead;
        if (!hasData()) {
            bytesRead = buffer.fillBuffer();
            if (bytesRead == -1) {
                eof = true;
            }
        } else {
            bytesRead = 0;
        }

        int i;
        int off = buffer.pos();
        for (;;) {
            i = buffer.indexOf(boundary, off, buffer.limit() - off);
            if (i == -1) {
                break;
            }
            // Make sure the boundary is either at the very beginning of the buffer
            // or preceded with LF
            if (i == buffer.pos() || buffer.byteAt(i - 1) == '\n') {
                int pos = i + boundary.length;
                int remaining = buffer.limit() - pos;
                if (remaining <= 0) {
                    // Make sure the boundary is terminated with EOS
                    break;
                } else {
                    // or with a whitespace or '-' char
                    char ch = (char)(buffer.byteAt(pos));
                    if (CharsetUtil.isWhitespace(ch) || ch == '-') {
                        break;
                    }
                }
            }
            off = i + boundary.length;
        }
        if (i != -1) {
            limit = i;
            atBoundary = true;
            calculateBoundaryLen();
        } else {
            if (eof) {
                limit = buffer.limit();
            } else {
                limit = buffer.limit() - (boundary.length + 2);
                                // [LF] [boundary] [CR][LF] minus one char
            }
        }
        return bytesRead;
    }

    public boolean isEmptyStream() {
        return initialLength == 0;
    }

    public boolean isFullyConsumed() {
        return completed && !buffer.hasBufferedData();
    }

    private void calculateBoundaryLen() throws IOException {
        boundaryLen = boundary.length;
        int len = limit - buffer.pos();
        if (len >= 0 && initialLength == -1) initialLength = len;
        if (len > 0) {
            if (buffer.byteAt(limit - 1) == '\n') {
                boundaryLen++;
                limit--;
            }
        }
        if (len > 1) {
            if (buffer.byteAt(limit - 1) == '\r') {
                boundaryLen++;
                limit--;
            }
        }
    }

    private void skipBoundary() throws IOException {
        if (!completed) {
            completed = true;
            buffer.skip(boundaryLen);
            boolean checkForLastPart = true;
            for (;;) {
                if (buffer.length() > 1) {
                    int ch1 = buffer.byteAt(buffer.pos());
                    int ch2 = buffer.byteAt(buffer.pos() + 1);

                    if (checkForLastPart) if (ch1 == '-' && ch2 == '-') {
                        this.lastPart = true;
                        buffer.skip(2);
                        checkForLastPart = false;
                        continue;
                    }

                    if (ch1 == '\r' && ch2 == '\n') {
                        buffer.skip(2);
                        break;
                    } else if (ch1 == '\n') {
                        buffer.skip(1);
                        break;
                    } else {
                        // ignoring everything in a line starting with a boundary.
                        buffer.skip(1);
                    }

                } else {
                    if (eof) {
                        break;
                    }
                    fillBuffer();
                }
            }
        }
    }

    public boolean isLastPart() {
        return lastPart;
    }

    public boolean eof() {
        return eof && !buffer.hasBufferedData();
    }

    @Override
    public String toString() {
        final StringBuilder buffer = new StringBuilder("MimeBoundaryInputStream, boundary ");
        for (byte b : boundary) {
            buffer.append((char) b);
        }
        return buffer.toString();
    }

    @Override
    public boolean unread(ByteArrayBuffer buf) {
        return false;
    }
}
