/*
 * @(#)SubImageInputStream.java  
 * 
 * Copyright (c) 2010 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package org.monte.media.io;

import java.io.IOException;
import javax.imageio.stream.ImageInputStream;

/**
 * SubImageInputStream.
 *
 * @author Werner Randelshofer
 * @version $Id: SubImageInputStream.java 134 2011-12-02 16:23:00Z werner $
 */
public class SubImageInputStream extends ImageInputStreamImpl2 {

    private ImageInputStream in;
    private long offset;
    private long length;

    public SubImageInputStream(ImageInputStream in, long offset, long length) throws IOException {
        this.in = in;
        this.offset = offset;
        this.length = length;
        if (in.length() != -1 && offset + length > in.length()) {
            throw new IllegalArgumentException("Offset too large. offset="+offset+" length="+length+" in.length="+in.length());
        }
       // setByteOrder(in.getByteOrder());
        in.seek(offset);
    }

    private long available() throws IOException {
        checkClosed();
        long pos = in.getStreamPosition();
        if (pos < offset) {
            in.seek(offset);
            pos = offset;
        }
        return offset + length - pos;
    }

    @Override
    public int read() throws IOException {
        if (available() <= 0) {
            return -1;
        } else {
            return in.read();
        }
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        long av = available();
        if (av <= 0) {
            return -1;
        } else {
            int result= in.read(b, off, (int) Math.min(len, av));
            return result;
        }
    }

    @Override
    public long getStreamPosition() throws IOException {
        return in.getStreamPosition() - offset;
    }

    @Override
    public void seek(long pos) throws IOException {
        in.seek(pos + offset);
    }

    @Override
    public void flush() throws IOException {
        in.flush();
    }

    @Override
    public long getFlushedPosition() {
        return in.getFlushedPosition() - offset;
    }

    /**
     * Default implementation returns false.  Subclasses should
     * override this if they cache data.
     */
    @Override
    public boolean isCached() {
        return in.isCached();
    }

    /**
     * Default implementation returns false.  Subclasses should
     * override this if they cache data in main memory.
     */
    @Override
    public boolean isCachedMemory() {
        return in.isCachedMemory();
    }

    @Override
    public boolean isCachedFile() {
        return in.isCachedFile();
    }

    @Override
    public long length() {
        return length;
    }
}
