/*
 * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.net.www;

import java.net.URL;
import java.util.*;
import java.io.*;
import sun.net.ProgressSource;
import sun.net.www.http.ChunkedInputStream;


public class MeteredStream extends FilterInputStream {

    // Instance variables.
    /* if expected != -1, after we've read >= expected, we're "closed" and return -1
     * from subsequest read() 's
     */
    protected boolean closed = false;
    protected long expected;
    protected long count = 0;
    protected long markedCount = 0;
    protected int markLimit = -1;
    protected ProgressSource pi;

    public MeteredStream(InputStream is, ProgressSource pi, long expected)
    {
        super(is);

        this.pi = pi;
        this.expected = expected;

        if (pi != null) {
            pi.updateProgress(0, expected);
        }
    }

    private final void justRead(long n) throws IOException   {
        if (n == -1) {

            /*
             * don't close automatically when mark is set and is valid;
             * cannot reset() after close()
             */
            if (!isMarked()) {
                close();
            }
            return;
        }

        count += n;

        /**
         * If read beyond the markLimit, invalidate the mark
         */
        if (count - markedCount > markLimit) {
            markLimit = -1;
        }

        if (pi != null)
            pi.updateProgress(count, expected);

        if (isMarked()) {
            return;
        }

        // if expected length is known, we could determine if
        // read overrun.
        if (expected > 0)   {
            if (count >= expected) {
                close();
            }
        }
    }

    /**
     * Returns true if the mark is valid, false otherwise
     */
    private boolean isMarked() {

        if (markLimit < 0) {
            return false;
        }

        // mark is set, but is not valid anymore
        if (count - markedCount > markLimit) {
           return false;
        }

        // mark still holds
        return true;
    }

    public synchronized int read() throws java.io.IOException {
        if (closed) {
            return -1;
        }
        int c = in.read();
        if (c != -1) {
            justRead(1);
        } else {
            justRead(c);
        }
        return c;
    }

    public synchronized int read(byte b[], int off, int len)
                throws java.io.IOException {
        if (closed) {
            return -1;
        }
        int n = in.read(b, off, len);
        justRead(n);
        return n;
    }

    public synchronized long skip(long n) throws IOException {

        // REMIND: what does skip do on EOF????
        if (closed) {
            return 0;
        }

        if (in instanceof ChunkedInputStream) {
            n = in.skip(n);
        }
        else {
            // just skip min(n, num_bytes_left)
            long min = (n > expected - count) ? expected - count: n;
            n = in.skip(min);
        }
        justRead(n);
        return n;
    }

    public void close() throws IOException {
        if (closed) {
            return;
        }
        if (pi != null)
            pi.finishTracking();

        closed = true;
        in.close();
    }

    public synchronized int available() throws IOException {
        return closed ? 0: in.available();
    }

    public synchronized void mark(int readLimit) {
        if (closed) {
            return;
        }
        super.mark(readLimit);

        /*
         * mark the count to restore upon reset
         */
        markedCount = count;
        markLimit = readLimit;
    }

    public synchronized void reset() throws IOException {
        if (closed) {
            return;
        }

        if (!isMarked()) {
            throw new IOException ("Resetting to an invalid mark");
        }

        count = markedCount;
        super.reset();
    }

    public boolean markSupported() {
        if (closed) {
            return false;
        }
        return super.markSupported();
    }

    protected void finalize() throws Throwable {
        try {
            close();
            if (pi != null)
                pi.close();
        }
        finally {
            // Call super class
            super.finalize();
        }
    }
}
