package com.jscape.util.io;

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

/**
 * @author Alex Usun
 */
public class ShiftByteBuffer {

    private final byte[] buffer;
    private int writePosition;
    private int readPosition;
    private int count;

    public ShiftByteBuffer(int size) {
        assertGreater(size, 0, "Bad buffer size value.");
        this.buffer = new byte[size];
    }

    public int size() {
        return this.buffer.length;
    }

    public boolean full() {
        return this.count == this.buffer.length;
    }

    public boolean empty() {
        return this.count == 0;
    }

    public int put(int data) {
        this.buffer[this.writePosition++] = (byte) data;
        adjustWritePosition();

        ++this.count;

        return this.count <= this.buffer.length ? -1 : get();
    }

    public int get() {
        if (empty()) {
            return -1;
        }

        int data = this.buffer[this.readPosition++] & 0xFF;
        adjustReadPosition();

        --this.count;

        return data;
    }

    public void clear() {
        this.writePosition = 0;
        this.readPosition = 0;
        this.count = 0;
    }

    public boolean equalsTo(byte[] data) {
        return equalsTo(data, 0, data.length);
    }

    public boolean equalsTo(byte[] data, int offset, int length) {
        if (length != this.count) {
            return false;
        }

        for (int i = 0, position = this.readPosition; i < length; ++i, ++position) {
            if (position == this.buffer.length) {
                position = 0;
            }

            if (data[offset + i] != this.buffer[position]) {
                return false;
            }
        }

        return true;
    }

    private void adjustWritePosition() {
        if (this.writePosition == this.buffer.length) {
            this.writePosition = 0;
        }
    }

    private void adjustReadPosition() {
        if (this.readPosition == this.buffer.length) {
            this.readPosition = 0;
        }
    }
}
