/*******************************************************************************
 * Copyright (c) 2008, 2010 SAP AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.mat.parser.io;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.eclipse.mat.parser.internal.Messages;

public class PositionInputStream extends FilterInputStream implements DataInput
{
    private final byte[] readBuffer = new byte[32];
    private long position = 0L;

    public PositionInputStream(InputStream in)
    {
        super(in);
    }

    public int read() throws IOException
    {
        int res = super.read();
        if (res != -1)
            position++;
        return res;
    }

    public int read(byte[] b, int off, int len) throws IOException
    {
        int res = super.read(b, off, len);
        if (res != -1)
            position += res;
        return res;
    }

    public long skip(long n) throws IOException
    {
        long res = super.skip(n);
        position += res;
        return res;
    }

    public boolean markSupported()
    {
        return false;
    }

    public void mark(int readLimit)
    {
        throw new UnsupportedOperationException(Messages.PositionInputStream_mark);
    }

    public void reset()
    {
        throw new UnsupportedOperationException(Messages.PositionInputStream_reset);
    }

    public final int skipBytes(int n) throws IOException
    {
        int total = 0;
        int cur = 0;

        while ((total < n) && ((cur = (int) skip(n - total)) > 0))
        {
            total += cur;
        }

        return total;
    }

    public final int skipBytes(long n) throws IOException
    {
        long total = 0;
        long cur = 0;

        while ((total < n) && ((cur = skip(n - total)) > 0))
        {
            total += cur;
        }

        return (int)total;
    }

    public final void readFully(byte b[]) throws IOException
    {
        readFully(b, 0, b.length);
    }

    public final void readFully(byte b[], int off, int len) throws IOException
    {
        int n = 0;
        while (n < len)
        {
            int count = read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
            n += count;
        }
    }

    public long position()
    {
        return position;
    }

    public void seek(long pos) throws IOException
    {
        if (in instanceof BufferedRandomAccessInputStream)
        {
            position = pos;
            ((BufferedRandomAccessInputStream) in).seek(pos);
        }
        else if (in instanceof SimpleBufferedRandomAccessInputStream)
        {
            position = pos;
            ((SimpleBufferedRandomAccessInputStream) in).seek(pos);
        }
        else
        {
            throw new UnsupportedOperationException(Messages.PositionInputStream_seek);
        }
    }

    // //////////////////////////////////////////////////////////////
    // DataInput implementations
    // //////////////////////////////////////////////////////////////

    public final int readUnsignedByte() throws IOException
    {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        position++;
        return ch;
    }

    public final int readInt() throws IOException
    {
        readFully(readBuffer, 0, 4);
        return readInt(readBuffer, 0);
    }

    public final long readLong() throws IOException
    {
        readFully(readBuffer, 0, 8);
        return readLong(readBuffer, 0);
    }

    public boolean readBoolean() throws IOException
    {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        position++;
        return (ch != 0);
    }

    public byte readByte() throws IOException
    {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        position++;
        return (byte) (ch);
    }

    public char readChar() throws IOException
    {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        position += 2;
        return (char) ((ch1 << 8) + (ch2 << 0));
    }

    public double readDouble() throws IOException
    {
        return Double.longBitsToDouble(readLong());
    }

    public float readFloat() throws IOException
    {
        return Float.intBitsToFloat(readInt());
    }

    public String readLine() throws IOException
    {
        throw new UnsupportedOperationException();
    }

    public short readShort() throws IOException
    {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        position += 2;
        return (short) ((ch1 << 8) + (ch2 << 0));
    }

    public String readUTF() throws IOException
    {
        return DataInputStream.readUTF(this);
    }

    public int readUnsignedShort() throws IOException
    {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        position += 2;
        return (ch1 << 8) + (ch2 << 0);
    }

    // //////////////////////////////////////////////////////////////
    // additions
    // //////////////////////////////////////////////////////////////

    public int readIntArray(int[] a) throws IOException
    {
        int len = a.length * 4;
        byte[] b = len > readBuffer.length ? new byte[len] : readBuffer;

        if (read(b, 0, len) != len)
            throw new IOException();

        for (int ii = 0; ii < a.length; ii++)
            a[ii] = readInt(b, ii * 4);

        return a.length;
    }

    private static final int readInt(byte[] b, int offset) throws IOException
    {
        int ch1 = b[offset] & 0xff;
        int ch2 = b[offset + 1] & 0xff;
        int ch3 = b[offset + 2] & 0xff;
        int ch4 = b[offset + 3] & 0xff;
        if ((ch1 | ch2 | ch3 | ch4) < 0)
            throw new EOFException();
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }

    public int readLongArray(long[] a) throws IOException
    {
        int len = a.length * 8;
        byte[] b = len > readBuffer.length ? new byte[len] : readBuffer;

        if (read(b, 0, len) != len)
            throw new IOException();

        for (int ii = 0; ii < a.length; ii++)
            a[ii] = readLong(b, ii * 8);

        return a.length;
    }

    private static final long readLong(byte[] b, int offset)
    {
        return (((long) b[offset] << 56) //
                        + ((long) (b[offset + 1] & 255) << 48) //
                        + ((long) (b[offset + 2] & 255) << 40) //
                        + ((long) (b[offset + 3] & 255) << 32) //
                        + ((long) (b[offset + 4] & 255) << 24) //
                        + ((b[offset + 5] & 255) << 16) //
                        + ((b[offset + 6] & 255) << 8) //
        + ((b[offset + 7] & 255) << 0));
    }

}
