package us.shandian.giga.postprocessing.io;

import org.schabi.newpipe.streams.io.SharpStream;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class ChunkFileInputStream extends SharpStream {

    private RandomAccessFile source;
    private final long offset;
    private final long length;
    private long position;

    public ChunkFileInputStream(File file, long start, long end, String mode) throws IOException {
        source = new RandomAccessFile(file, mode);
        offset = start;
        length = end - start;
        position = 0;

        if (length < 1) {
            source.close();
            throw new IOException("The chunk is empty or invalid");
        }
        if (source.length() < end) {
            try {
                throw new IOException(String.format("invalid file length. expected = %s  found = %s", end, source.length()));
            } finally {
                source.close();
            }
        }

        source.seek(offset);
    }

    /**
     * Get absolute position on file
     *
     * @return the position
     */
    public long getFilePointer() {
        return offset + position;
    }

    @Override
    public int read() throws IOException {
        if ((position + 1) > length) {
            return 0;
        }

        int res = source.read();
        if (res >= 0) {
            position++;
        }

        return res;
    }

    @Override
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    @Override
    public int read(byte b[], int off, int len) throws IOException {
        if ((position + len) > length) {
            len = (int) (length - position);
        }
        if (len == 0) {
            return 0;
        }

        int res = source.read(b, off, len);
        position += res;

        return res;
    }

    @Override
    public long skip(long pos) throws IOException {
        pos = Math.min(pos + position, length);

        if (pos == 0) {
            return 0;
        }

        source.seek(offset + pos);

        long oldPos = position;
        position = pos;

        return pos - oldPos;
    }

    @Override
    public int available() {
        return (int) (length - position);
    }

    @SuppressWarnings("EmptyCatchBlock")
    @Override
    public void dispose() {
        try {
            source.close();
        } catch (IOException err) {
        } finally {
            source = null;
        }
    }

    @Override
    public boolean isDisposed() {
        return source == null;
    }

    @Override
    public void rewind() throws IOException {
        position = 0;
        source.seek(offset);
    }

    @Override
    public boolean canRewind() {
        return true;
    }

    @Override
    public boolean canRead() {
        return true;
    }

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

    @Override
    public void write(byte value) {
    }

    @Override
    public void write(byte[] buffer) {
    }

    @Override
    public void write(byte[] buffer, int offset, int count) {
    }

    @Override
    public void flush() {
    }
}
