package com.jscape.util.io;

import java.io.InputStream;

import static com.jscape.util.Parameters.assertNotNull;

/**
 * @author Alex Usun
 */
public class ByteArrayInputStream
        extends InputStream {

    private byte[] oneByteBuffer;
    private byte[] buffer;
    private int offset;
    private int length;

    public static ByteArrayInputStream empty() {
        return new ByteArrayInputStream(new byte[0]);
    }

    public ByteArrayInputStream(byte[] data, int offset, int length) {
        put(data, offset, length);
    }

    public ByteArrayInputStream(byte[] data) {
        this(data, 0, data.length);
    }

    public void put(byte[] data, int offset, int length) {
        assertNotNull(data);
        this.buffer = data;

        this.offset = offset;
        this.length = length;
    }

    @Override
    public int read() {
        if (this.oneByteBuffer == null) {
            this.oneByteBuffer = new byte[1];
        }

        int read;

        do {
            read = read(this.oneByteBuffer);
        } while (read == 0);

        return read != -1 ? this.oneByteBuffer[0] & 0xFF : -1;
    }

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

    @Override
    public int read(byte[] buffer, int offset, int length) {
        if (this.length == 0) {
            return -1;
        }

        length = Math.min(length, this.length);
        System.arraycopy(this.buffer, this.offset, buffer, offset, length);
        this.offset += length;
        this.length -= length;

        return length;
    }

    @Override
    public int available() {
        return this.length;
    }

    @Override
    public void close() {
        // empty
    }

    @Override
    public String toString() {
        return "ByteArrayInputStream {"
                + "buffer.length=" + this.buffer.length
                + ", offset=" + this.offset
                + ", length=" + this.length
                + '}';
    }
}
